[
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n   <img src=\"assets/icon.png\" alt=\"icon\" width=\"200px\"/>\n</p>\n\n# (CVPR 2025) Adversarial Diffusion Compression for Real-World Image Super-Resolution [PyTorch]\n\n[![icon](https://img.shields.io/badge/ArXiv-Paper-<COLOR>.svg)](https://arxiv.org/abs/2411.13383) [![Hugging Face](https://img.shields.io/badge/Code_&_Models-%F0%9F%A4%97%20Hugging%20Face-blue)](https://huggingface.co/Guaishou74851/AdcSR) ![visitors](https://visitor-badge.laobi.icu/badge?page_id=Guaishou74851.AdcSR)\n\n[Bin Chen](https://scholar.google.com/citations?user=aZDNm98AAAAJ)<sup>1,3,\\*</sup>\n| [Gehui Li](https://github.com/cvsym)<sup>1,\\*</sup>\n| [Rongyuan Wu](https://scholar.google.com/citations?user=A-U8zE8AAAAJ)<sup>2,3,\\*</sup>\n| [Xindong Zhang](https://scholar.google.com/citations?user=q76RnqIAAAAJ)<sup>3</sup>\n| [Jie Chen](https://aimia-pku.github.io/)<sup>1,†</sup>\n| [Jian Zhang](https://jianzhang.tech/)<sup>1,†</sup>\n| [Lei Zhang](https://www4.comp.polyu.edu.hk/~cslzhang/)<sup>2,3</sup>\n\n<sup>1</sup> *School of Electronic and Computer Engineering, Peking University*\n\n<sup>2</sup> *The Hong Kong Polytechnic University*, <sup>3</sup> *OPPO Research Institute*\n\n<sup>*</sup> Equal Contribution. <sup>†</sup> Corresponding Authors.\n\n⭐ **If AdcSR is helpful to you, please star this repo. Thanks!** 🤗\n\n## 📝 Overview\n\n### Highlights\n\n- **Adversarial Diffusion Compression (ADC).** We remove and prune redundant modules from the one-step diffusion network [OSEDiff](https://github.com/cswry/OSEDiff) and apply adversarial distillation to retain generative capabilities despite reduced capacity.\n- **Real-Time [Stable Diffusion](https://huggingface.co/stabilityai/stable-diffusion-2-1)-Based Image Super-Resolution.** AdcSR super-resolves a 128×128 image to 512×512 **in just 0.03s 🚀** on an A100 GPU.\n- **Competitive Visual Quality.** Despite **74% fewer parameters 📉** than [OSEDiff](https://github.com/cswry/OSEDiff), AdcSR achieves **competitive image quality** across multiple benchmarks.\n\n### Framework\n\n1. **Structural Compression**\n   - **Removable modules** (VAE encoder, text prompt extractor, cross-attention, time embeddings) are eliminated.\n   - **Prunable modules** (UNet, VAE decoder) are **channel-pruned** to optimize efficiency while preserving performance.\n\n<p align=\"center\">\n   <img src=\"assets/teaser.png\" alt=\"teaser\" width=\"55%\"/>\n</p>\n\n2. **Two-Stage Training**\n   1. **Pretraining a Pruned VAE Decoder** to maintain its ability to decode latent representations.\n   2. **Adversarial Distillation** to align compressed network features with the teacher model (e.g., [OSEDiff](https://github.com/cswry/OSEDiff)) and ground truth images.\n\n<p align=\"center\">\n   <img src=\"assets/method.png\" alt=\"method\" />\n</p>\n\n## 😍 Visual Results\n\n[<img src=\"assets/demo1.png\" height=\"240px\"/>](https://imgsli.com/MzU2MjU1) [<img src=\"assets/demo2.png\" height=\"240px\"/>](https://imgsli.com/MzU2MjU2) [<img src=\"assets/demo3.png\" height=\"240px\"/>](https://imgsli.com/MzU2MjU3)\n\n[<img src=\"assets/demo4.png\" height=\"242px\"/>](https://imgsli.com/MzU2NTg4) [<img src=\"assets/demo5.png\" height=\"242px\"/>](https://imgsli.com/MzU2NTkw) [<img src=\"assets/demo6.png\" height=\"242px\"/>](https://imgsli.com/MzU2NTk1)\n\n[<img src=\"assets/demo7.png\" height=\"319px\"/>](https://imgsli.com/MzU2OTE0) [<img src=\"assets/demo8.png\" height=\"319px\"/>](https://imgsli.com/MzU2OTE1)\n\nhttps://github.com/user-attachments/assets/1211cefa-8704-47f5-82cd-ec4ef084b9ec\n\n<img src=\"assets/comp.png\" alt=\"comp\" width=\"840px\" />\n\n## ⚙ Installation\n\n```shell\ngit clone https://github.com/Guaishou74851/AdcSR.git\ncd AdcSR\nconda create -n AdcSR python=3.10\nconda activate AdcSR\npip install --upgrade pip\npip install -r requirements.txt\nchmod +x train.sh train_debug.sh test_debug.sh evaluate_debug.sh\n```\n\n## ⚡ Test\n\n1. **Download test datasets** (`DIV2K-Val.zip`, `DRealSR.zip`, `RealSR.zip`) from [Hugging Face](https://huggingface.co/Guaishou74851/AdcSR) or [PKU Disk](https://disk.pku.edu.cn/link/AAD499197CBF054392BC4061F904CC4026).\n2. **Unzip** them into `./testset/`, ensuring the structure:\n   ```\n   ./testset/DIV2K-Val/LR/xxx.png\n   ./testset/DIV2K-Val/HR/xxx.png\n   ./testset/DRealSR/LR/xxx.png\n   ./testset/DRealSR/HR/xxx.png\n   ./testset/RealSR/LR/xxx.png\n   ./testset/RealSR/HR/xxx.png\n   ```\n3. **Download model weights** (`net_params_200.pkl`) from the same link and place it in `./weight/`.  \n4. **Run the test script** (or modify and execute `./test_debug.sh` for convenience):  \n   ```bash\n   python test.py --LR_dir=path_to_LR_images --SR_dir=path_to_SR_images\n   ```\n   The results will be saved in `path_to_SR_images`.\n5. **Test Your Own Images**:\n   - Place your **low-resolution (LR)** images into `./testset/xxx/`.\n   - Run the command with `--LR_dir=./testset/xxx/ --SR_dir=./yyy/`, and the model will perform **x4 super-resolution**.\n\n## 🍭 Evaluation\n\nRun the evaluation script (or modify and execute `./evaluate_debug.sh` for convenience):\n```bash\npython evaluate.py --HR_dir=path_to_HR_images --SR_dir=path_to_SR_images\n```\n\n## 🔥 Train\n\nThis repo provides code for **Stage 2** training (**adversarial distillation**). For **Stage 1** (pretraining the channel-pruned VAE decoder), refer to our paper and use the code of [Latent Diffusion Models](https://github.com/CompVis/latent-diffusion) repo.\n\n1. **Download pretrained model weights** (`DAPE.pth`, `halfDecoder.ckpt`, `osediff.pkl`, `ram_swin_large_14m.pth`) from [Hugging Face](https://huggingface.co/Guaishou74851/AdcSR) or [PKU Disk](https://disk.pku.edu.cn/link/AAD499197CBF054392BC4061F904CC4026), and place them in `./weight/pretrained/`.\n2. **Download the [LSDIR](https://huggingface.co/ofsoundof/LSDIR) dataset** and store it in your preferred location.\n3. **Modify the dataset path** in `config.yml`:\n   ```yaml\n   dataroot_gt: path_to_HR_images_of_LSDIR\n   ```\n4. **Run the training script** (or modify and execute `./train.sh` or `./train_debug.sh`):\n   ```bash\n   CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python -m torch.distributed.run --nproc_per_node=8 --master_port=23333 train.py\n   ```\n   The trained model will be saved in `./weight/`.\n   \n## 🥰 Acknowledgement\n\nThis project is built upon the codes of [Latent Diffusion Models](https://github.com/CompVis/latent-diffusion), [Diffusers](https://github.com/huggingface/diffusers), [BasicSR](https://github.com/XPixelGroup/BasicSR), and [OSEDiff](https://github.com/cswry/OSEDiff). We sincerely thank the authors of these repos for their significant contributions.\n\n## 🎓 Citation\n\nIf you find our work helpful, please consider citing:\n\n```latex\n@inproceedings{chen2025adversarial,\n  title={Adversarial Diffusion Compression for Real-World Image Super-Resolution},\n  author={Chen, Bin and Li, Gehui and Wu, Rongyuan and Zhang, Xindong and Chen, Jie and Zhang, Jian and Zhang, Lei},\n  booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},\n  year={2025}\n}\n```\n"
  },
  {
    "path": "bsr/degradations.py",
    "content": "import cv2\nimport math\nimport numpy as np\nimport random\nimport torch\nfrom scipy import special\nfrom scipy.stats import multivariate_normal\nfrom torchvision.transforms._functional_tensor import rgb_to_grayscale\n\n# -------------------------------------------------------------------- #\n# --------------------------- blur kernels --------------------------- #\n# -------------------------------------------------------------------- #\n\n\n# --------------------------- util functions --------------------------- #\ndef sigma_matrix2(sig_x, sig_y, theta):\n    \"\"\"Calculate the rotated sigma matrix (two dimensional matrix).\n\n    Args:\n        sig_x (float):\n        sig_y (float):\n        theta (float): Radian measurement.\n\n    Returns:\n        ndarray: Rotated sigma matrix.\n    \"\"\"\n    d_matrix = np.array([[sig_x**2, 0], [0, sig_y**2]])\n    u_matrix = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])\n    return np.dot(u_matrix, np.dot(d_matrix, u_matrix.T))\n\n\ndef mesh_grid(kernel_size):\n    \"\"\"Generate the mesh grid, centering at zero.\n\n    Args:\n        kernel_size (int):\n\n    Returns:\n        xy (ndarray): with the shape (kernel_size, kernel_size, 2)\n        xx (ndarray): with the shape (kernel_size, kernel_size)\n        yy (ndarray): with the shape (kernel_size, kernel_size)\n    \"\"\"\n    ax = np.arange(-kernel_size // 2 + 1., kernel_size // 2 + 1.)\n    xx, yy = np.meshgrid(ax, ax)\n    xy = np.hstack((xx.reshape((kernel_size * kernel_size, 1)), yy.reshape(kernel_size * kernel_size,\n                                                                           1))).reshape(kernel_size, kernel_size, 2)\n    return xy, xx, yy\n\n\ndef pdf2(sigma_matrix, grid):\n    \"\"\"Calculate PDF of the bivariate Gaussian distribution.\n\n    Args:\n        sigma_matrix (ndarray): with the shape (2, 2)\n        grid (ndarray): generated by :func:`mesh_grid`,\n            with the shape (K, K, 2), K is the kernel size.\n\n    Returns:\n        kernel (ndarrray): un-normalized kernel.\n    \"\"\"\n    inverse_sigma = np.linalg.inv(sigma_matrix)\n    kernel = np.exp(-0.5 * np.sum(np.dot(grid, inverse_sigma) * grid, 2))\n    return kernel\n\n\ndef cdf2(d_matrix, grid):\n    \"\"\"Calculate the CDF of the standard bivariate Gaussian distribution.\n        Used in skewed Gaussian distribution.\n\n    Args:\n        d_matrix (ndarrasy): skew matrix.\n        grid (ndarray): generated by :func:`mesh_grid`,\n            with the shape (K, K, 2), K is the kernel size.\n\n    Returns:\n        cdf (ndarray): skewed cdf.\n    \"\"\"\n    rv = multivariate_normal([0, 0], [[1, 0], [0, 1]])\n    grid = np.dot(grid, d_matrix)\n    cdf = rv.cdf(grid)\n    return cdf\n\n\ndef bivariate_Gaussian(kernel_size, sig_x, sig_y, theta, grid=None, isotropic=True):\n    \"\"\"Generate a bivariate isotropic or anisotropic Gaussian kernel.\n\n    In the isotropic mode, only `sig_x` is used. `sig_y` and `theta` is ignored.\n\n    Args:\n        kernel_size (int):\n        sig_x (float):\n        sig_y (float):\n        theta (float): Radian measurement.\n        grid (ndarray, optional): generated by :func:`mesh_grid`,\n            with the shape (K, K, 2), K is the kernel size. Default: None\n        isotropic (bool):\n\n    Returns:\n        kernel (ndarray): normalized kernel.\n    \"\"\"\n    if grid is None:\n        grid, _, _ = mesh_grid(kernel_size)\n    if isotropic:\n        sigma_matrix = np.array([[sig_x**2, 0], [0, sig_x**2]])\n    else:\n        sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)\n    kernel = pdf2(sigma_matrix, grid)\n    kernel = kernel / np.sum(kernel)\n    return kernel\n\n\ndef bivariate_generalized_Gaussian(kernel_size, sig_x, sig_y, theta, beta, grid=None, isotropic=True):\n    \"\"\"Generate a bivariate generalized Gaussian kernel.\n\n    ``Paper: Parameter Estimation For Multivariate Generalized Gaussian Distributions``\n\n    In the isotropic mode, only `sig_x` is used. `sig_y` and `theta` is ignored.\n\n    Args:\n        kernel_size (int):\n        sig_x (float):\n        sig_y (float):\n        theta (float): Radian measurement.\n        beta (float): shape parameter, beta = 1 is the normal distribution.\n        grid (ndarray, optional): generated by :func:`mesh_grid`,\n            with the shape (K, K, 2), K is the kernel size. Default: None\n\n    Returns:\n        kernel (ndarray): normalized kernel.\n    \"\"\"\n    if grid is None:\n        grid, _, _ = mesh_grid(kernel_size)\n    if isotropic:\n        sigma_matrix = np.array([[sig_x**2, 0], [0, sig_x**2]])\n    else:\n        sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)\n    inverse_sigma = np.linalg.inv(sigma_matrix)\n    kernel = np.exp(-0.5 * np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta))\n    kernel = kernel / np.sum(kernel)\n    return kernel\n\n\ndef bivariate_plateau(kernel_size, sig_x, sig_y, theta, beta, grid=None, isotropic=True):\n    \"\"\"Generate a plateau-like anisotropic kernel.\n\n    1 / (1+x^(beta))\n\n    Reference: https://stats.stackexchange.com/questions/203629/is-there-a-plateau-shaped-distribution\n\n    In the isotropic mode, only `sig_x` is used. `sig_y` and `theta` is ignored.\n\n    Args:\n        kernel_size (int):\n        sig_x (float):\n        sig_y (float):\n        theta (float): Radian measurement.\n        beta (float): shape parameter, beta = 1 is the normal distribution.\n        grid (ndarray, optional): generated by :func:`mesh_grid`,\n            with the shape (K, K, 2), K is the kernel size. Default: None\n\n    Returns:\n        kernel (ndarray): normalized kernel.\n    \"\"\"\n    if grid is None:\n        grid, _, _ = mesh_grid(kernel_size)\n    if isotropic:\n        sigma_matrix = np.array([[sig_x**2, 0], [0, sig_x**2]])\n    else:\n        sigma_matrix = sigma_matrix2(sig_x, sig_y, theta)\n    inverse_sigma = np.linalg.inv(sigma_matrix)\n    kernel = np.reciprocal(np.power(np.sum(np.dot(grid, inverse_sigma) * grid, 2), beta) + 1)\n    kernel = kernel / np.sum(kernel)\n    return kernel\n\n\ndef random_bivariate_Gaussian(kernel_size,\n                              sigma_x_range,\n                              sigma_y_range,\n                              rotation_range,\n                              noise_range=None,\n                              isotropic=True):\n    \"\"\"Randomly generate bivariate isotropic or anisotropic Gaussian kernels.\n\n    In the isotropic mode, only `sigma_x_range` is used. `sigma_y_range` and `rotation_range` is ignored.\n\n    Args:\n        kernel_size (int):\n        sigma_x_range (tuple): [0.6, 5]\n        sigma_y_range (tuple): [0.6, 5]\n        rotation range (tuple): [-math.pi, math.pi]\n        noise_range(tuple, optional): multiplicative kernel noise,\n            [0.75, 1.25]. Default: None\n\n    Returns:\n        kernel (ndarray):\n    \"\"\"\n    assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'\n    assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'\n    sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])\n    if isotropic is False:\n        assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'\n        assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'\n        sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])\n        rotation = np.random.uniform(rotation_range[0], rotation_range[1])\n    else:\n        sigma_y = sigma_x\n        rotation = 0\n\n    kernel = bivariate_Gaussian(kernel_size, sigma_x, sigma_y, rotation, isotropic=isotropic)\n\n    # add multiplicative noise\n    if noise_range is not None:\n        assert noise_range[0] < noise_range[1], 'Wrong noise range.'\n        noise = np.random.uniform(noise_range[0], noise_range[1], size=kernel.shape)\n        kernel = kernel * noise\n    kernel = kernel / np.sum(kernel)\n    return kernel\n\n\ndef random_bivariate_generalized_Gaussian(kernel_size,\n                                          sigma_x_range,\n                                          sigma_y_range,\n                                          rotation_range,\n                                          beta_range,\n                                          noise_range=None,\n                                          isotropic=True):\n    \"\"\"Randomly generate bivariate generalized Gaussian kernels.\n\n    In the isotropic mode, only `sigma_x_range` is used. `sigma_y_range` and `rotation_range` is ignored.\n\n    Args:\n        kernel_size (int):\n        sigma_x_range (tuple): [0.6, 5]\n        sigma_y_range (tuple): [0.6, 5]\n        rotation range (tuple): [-math.pi, math.pi]\n        beta_range (tuple): [0.5, 8]\n        noise_range(tuple, optional): multiplicative kernel noise,\n            [0.75, 1.25]. Default: None\n\n    Returns:\n        kernel (ndarray):\n    \"\"\"\n    assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'\n    assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'\n    sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])\n    if isotropic is False:\n        assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'\n        assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'\n        sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])\n        rotation = np.random.uniform(rotation_range[0], rotation_range[1])\n    else:\n        sigma_y = sigma_x\n        rotation = 0\n\n    # assume beta_range[0] < 1 < beta_range[1]\n    if np.random.uniform() < 0.5:\n        beta = np.random.uniform(beta_range[0], 1)\n    else:\n        beta = np.random.uniform(1, beta_range[1])\n\n    kernel = bivariate_generalized_Gaussian(kernel_size, sigma_x, sigma_y, rotation, beta, isotropic=isotropic)\n\n    # add multiplicative noise\n    if noise_range is not None:\n        assert noise_range[0] < noise_range[1], 'Wrong noise range.'\n        noise = np.random.uniform(noise_range[0], noise_range[1], size=kernel.shape)\n        kernel = kernel * noise\n    kernel = kernel / np.sum(kernel)\n    return kernel\n\n\ndef random_bivariate_plateau(kernel_size,\n                             sigma_x_range,\n                             sigma_y_range,\n                             rotation_range,\n                             beta_range,\n                             noise_range=None,\n                             isotropic=True):\n    \"\"\"Randomly generate bivariate plateau kernels.\n\n    In the isotropic mode, only `sigma_x_range` is used. `sigma_y_range` and `rotation_range` is ignored.\n\n    Args:\n        kernel_size (int):\n        sigma_x_range (tuple): [0.6, 5]\n        sigma_y_range (tuple): [0.6, 5]\n        rotation range (tuple): [-math.pi/2, math.pi/2]\n        beta_range (tuple): [1, 4]\n        noise_range(tuple, optional): multiplicative kernel noise,\n            [0.75, 1.25]. Default: None\n\n    Returns:\n        kernel (ndarray):\n    \"\"\"\n    assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'\n    assert sigma_x_range[0] < sigma_x_range[1], 'Wrong sigma_x_range.'\n    sigma_x = np.random.uniform(sigma_x_range[0], sigma_x_range[1])\n    if isotropic is False:\n        assert sigma_y_range[0] < sigma_y_range[1], 'Wrong sigma_y_range.'\n        assert rotation_range[0] < rotation_range[1], 'Wrong rotation_range.'\n        sigma_y = np.random.uniform(sigma_y_range[0], sigma_y_range[1])\n        rotation = np.random.uniform(rotation_range[0], rotation_range[1])\n    else:\n        sigma_y = sigma_x\n        rotation = 0\n\n    # TODO: this may be not proper\n    if np.random.uniform() < 0.5:\n        beta = np.random.uniform(beta_range[0], 1)\n    else:\n        beta = np.random.uniform(1, beta_range[1])\n\n    kernel = bivariate_plateau(kernel_size, sigma_x, sigma_y, rotation, beta, isotropic=isotropic)\n    # add multiplicative noise\n    if noise_range is not None:\n        assert noise_range[0] < noise_range[1], 'Wrong noise range.'\n        noise = np.random.uniform(noise_range[0], noise_range[1], size=kernel.shape)\n        kernel = kernel * noise\n    kernel = kernel / np.sum(kernel)\n\n    return kernel\n\n\ndef random_mixed_kernels(kernel_list,\n                         kernel_prob,\n                         kernel_size=21,\n                         sigma_x_range=(0.6, 5),\n                         sigma_y_range=(0.6, 5),\n                         rotation_range=(-math.pi, math.pi),\n                         betag_range=(0.5, 8),\n                         betap_range=(0.5, 8),\n                         noise_range=None):\n    \"\"\"Randomly generate mixed kernels.\n\n    Args:\n        kernel_list (tuple): a list name of kernel types,\n            support ['iso', 'aniso', 'skew', 'generalized', 'plateau_iso',\n            'plateau_aniso']\n        kernel_prob (tuple): corresponding kernel probability for each\n            kernel type\n        kernel_size (int):\n        sigma_x_range (tuple): [0.6, 5]\n        sigma_y_range (tuple): [0.6, 5]\n        rotation range (tuple): [-math.pi, math.pi]\n        beta_range (tuple): [0.5, 8]\n        noise_range(tuple, optional): multiplicative kernel noise,\n            [0.75, 1.25]. Default: None\n\n    Returns:\n        kernel (ndarray):\n    \"\"\"\n    kernel_type = random.choices(kernel_list, kernel_prob)[0]\n    if kernel_type == 'iso':\n        kernel = random_bivariate_Gaussian(\n            kernel_size, sigma_x_range, sigma_y_range, rotation_range, noise_range=noise_range, isotropic=True)\n    elif kernel_type == 'aniso':\n        kernel = random_bivariate_Gaussian(\n            kernel_size, sigma_x_range, sigma_y_range, rotation_range, noise_range=noise_range, isotropic=False)\n    elif kernel_type == 'generalized_iso':\n        kernel = random_bivariate_generalized_Gaussian(\n            kernel_size,\n            sigma_x_range,\n            sigma_y_range,\n            rotation_range,\n            betag_range,\n            noise_range=noise_range,\n            isotropic=True)\n    elif kernel_type == 'generalized_aniso':\n        kernel = random_bivariate_generalized_Gaussian(\n            kernel_size,\n            sigma_x_range,\n            sigma_y_range,\n            rotation_range,\n            betag_range,\n            noise_range=noise_range,\n            isotropic=False)\n    elif kernel_type == 'plateau_iso':\n        kernel = random_bivariate_plateau(\n            kernel_size, sigma_x_range, sigma_y_range, rotation_range, betap_range, noise_range=None, isotropic=True)\n    elif kernel_type == 'plateau_aniso':\n        kernel = random_bivariate_plateau(\n            kernel_size, sigma_x_range, sigma_y_range, rotation_range, betap_range, noise_range=None, isotropic=False)\n    return kernel\n\n\nnp.seterr(divide='ignore', invalid='ignore')\n\n\ndef circular_lowpass_kernel(cutoff, kernel_size, pad_to=0):\n    \"\"\"2D sinc filter\n\n    Reference: https://dsp.stackexchange.com/questions/58301/2-d-circularly-symmetric-low-pass-filter\n\n    Args:\n        cutoff (float): cutoff frequency in radians (pi is max)\n        kernel_size (int): horizontal and vertical size, must be odd.\n        pad_to (int): pad kernel size to desired size, must be odd or zero.\n    \"\"\"\n    assert kernel_size % 2 == 1, 'Kernel size must be an odd number.'\n    kernel = np.fromfunction(\n        lambda x, y: cutoff * special.j1(cutoff * np.sqrt(\n            (x - (kernel_size - 1) / 2)**2 + (y - (kernel_size - 1) / 2)**2)) / (2 * np.pi * np.sqrt(\n                (x - (kernel_size - 1) / 2)**2 + (y - (kernel_size - 1) / 2)**2)), [kernel_size, kernel_size])\n    kernel[(kernel_size - 1) // 2, (kernel_size - 1) // 2] = cutoff**2 / (4 * np.pi)\n    kernel = kernel / np.sum(kernel)\n    if pad_to > kernel_size:\n        pad_size = (pad_to - kernel_size) // 2\n        kernel = np.pad(kernel, ((pad_size, pad_size), (pad_size, pad_size)))\n    return kernel\n\n\n# ------------------------------------------------------------- #\n# --------------------------- noise --------------------------- #\n# ------------------------------------------------------------- #\n\n# ----------------------- Gaussian Noise ----------------------- #\n\n\ndef generate_gaussian_noise(img, sigma=10, gray_noise=False):\n    \"\"\"Generate Gaussian noise.\n\n    Args:\n        img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.\n        sigma (float): Noise scale (measured in range 255). Default: 10.\n\n    Returns:\n        (Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],\n            float32.\n    \"\"\"\n    if gray_noise:\n        noise = np.float32(np.random.randn(*(img.shape[0:2]))) * sigma / 255.\n        noise = np.expand_dims(noise, axis=2).repeat(3, axis=2)\n    else:\n        noise = np.float32(np.random.randn(*(img.shape))) * sigma / 255.\n    return noise\n\n\ndef add_gaussian_noise(img, sigma=10, clip=True, rounds=False, gray_noise=False):\n    \"\"\"Add Gaussian noise.\n\n    Args:\n        img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.\n        sigma (float): Noise scale (measured in range 255). Default: 10.\n\n    Returns:\n        (Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],\n            float32.\n    \"\"\"\n    noise = generate_gaussian_noise(img, sigma, gray_noise)\n    out = img + noise\n    if clip and rounds:\n        out = np.clip((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = np.clip(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\ndef generate_gaussian_noise_pt(img, sigma=10, gray_noise=0):\n    \"\"\"Add Gaussian noise (PyTorch version).\n\n    Args:\n        img (Tensor): Shape (b, c, h, w), range[0, 1], float32.\n        scale (float | Tensor): Noise scale. Default: 1.0.\n\n    Returns:\n        (Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],\n            float32.\n    \"\"\"\n    b, _, h, w = img.size()\n    if not isinstance(sigma, (float, int)):\n        sigma = sigma.view(img.size(0), 1, 1, 1)\n    if isinstance(gray_noise, (float, int)):\n        cal_gray_noise = gray_noise > 0\n    else:\n        gray_noise = gray_noise.view(b, 1, 1, 1)\n        cal_gray_noise = torch.sum(gray_noise) > 0\n\n    if cal_gray_noise:\n        noise_gray = torch.randn(*img.size()[2:4], dtype=img.dtype, device=img.device) * sigma / 255.\n        noise_gray = noise_gray.view(b, 1, h, w)\n\n    # always calculate color noise\n    noise = torch.randn(*img.size(), dtype=img.dtype, device=img.device) * sigma / 255.\n\n    if cal_gray_noise:\n        noise = noise * (1 - gray_noise) + noise_gray * gray_noise\n    return noise\n\n\ndef add_gaussian_noise_pt(img, sigma=10, gray_noise=0, clip=True, rounds=False):\n    \"\"\"Add Gaussian noise (PyTorch version).\n\n    Args:\n        img (Tensor): Shape (b, c, h, w), range[0, 1], float32.\n        scale (float | Tensor): Noise scale. Default: 1.0.\n\n    Returns:\n        (Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],\n            float32.\n    \"\"\"\n    noise = generate_gaussian_noise_pt(img, sigma, gray_noise)\n    out = img + noise\n    if clip and rounds:\n        out = torch.clamp((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = torch.clamp(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\n# ----------------------- Random Gaussian Noise ----------------------- #\ndef random_generate_gaussian_noise(img, sigma_range=(0, 10), gray_prob=0):\n    sigma = np.random.uniform(sigma_range[0], sigma_range[1])\n    if np.random.uniform() < gray_prob:\n        gray_noise = True\n    else:\n        gray_noise = False\n    return generate_gaussian_noise(img, sigma, gray_noise)\n\n\ndef random_add_gaussian_noise(img, sigma_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):\n    noise = random_generate_gaussian_noise(img, sigma_range, gray_prob)\n    out = img + noise\n    if clip and rounds:\n        out = np.clip((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = np.clip(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\ndef random_generate_gaussian_noise_pt(img, sigma_range=(0, 10), gray_prob=0):\n    sigma = torch.rand(\n        img.size(0), dtype=img.dtype, device=img.device) * (sigma_range[1] - sigma_range[0]) + sigma_range[0]\n    gray_noise = torch.rand(img.size(0), dtype=img.dtype, device=img.device)\n    gray_noise = (gray_noise < gray_prob).float()\n    return generate_gaussian_noise_pt(img, sigma, gray_noise)\n\n\ndef random_add_gaussian_noise_pt(img, sigma_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):\n    noise = random_generate_gaussian_noise_pt(img, sigma_range, gray_prob)\n    out = img + noise\n    if clip and rounds:\n        out = torch.clamp((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = torch.clamp(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\n# ----------------------- Poisson (Shot) Noise ----------------------- #\n\n\ndef generate_poisson_noise(img, scale=1.0, gray_noise=False):\n    \"\"\"Generate poisson noise.\n\n    Reference: https://github.com/scikit-image/scikit-image/blob/main/skimage/util/noise.py#L37-L219\n\n    Args:\n        img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.\n        scale (float): Noise scale. Default: 1.0.\n        gray_noise (bool): Whether generate gray noise. Default: False.\n\n    Returns:\n        (Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],\n            float32.\n    \"\"\"\n    if gray_noise:\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n    # round and clip image for counting vals correctly\n    img = np.clip((img * 255.0).round(), 0, 255) / 255.\n    vals = len(np.unique(img))\n    vals = 2**np.ceil(np.log2(vals))\n    out = np.float32(np.random.poisson(img * vals) / float(vals))\n    noise = out - img\n    if gray_noise:\n        noise = np.repeat(noise[:, :, np.newaxis], 3, axis=2)\n    return noise * scale\n\n\ndef add_poisson_noise(img, scale=1.0, clip=True, rounds=False, gray_noise=False):\n    \"\"\"Add poisson noise.\n\n    Args:\n        img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.\n        scale (float): Noise scale. Default: 1.0.\n        gray_noise (bool): Whether generate gray noise. Default: False.\n\n    Returns:\n        (Numpy array): Returned noisy image, shape (h, w, c), range[0, 1],\n            float32.\n    \"\"\"\n    noise = generate_poisson_noise(img, scale, gray_noise)\n    out = img + noise\n    if clip and rounds:\n        out = np.clip((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = np.clip(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\ndef generate_poisson_noise_pt(img, scale=1.0, gray_noise=0):\n    \"\"\"Generate a batch of poisson noise (PyTorch version)\n\n    Args:\n        img (Tensor): Input image, shape (b, c, h, w), range [0, 1], float32.\n        scale (float | Tensor): Noise scale. Number or Tensor with shape (b).\n            Default: 1.0.\n        gray_noise (float | Tensor): 0-1 number or Tensor with shape (b).\n            0 for False, 1 for True. Default: 0.\n\n    Returns:\n        (Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],\n            float32.\n    \"\"\"\n    b, _, h, w = img.size()\n    if isinstance(gray_noise, (float, int)):\n        cal_gray_noise = gray_noise > 0\n    else:\n        gray_noise = gray_noise.view(b, 1, 1, 1)\n        cal_gray_noise = torch.sum(gray_noise) > 0\n    if cal_gray_noise:\n        img_gray = rgb_to_grayscale(img, num_output_channels=1)\n        # round and clip image for counting vals correctly\n        img_gray = torch.clamp((img_gray * 255.0).round(), 0, 255) / 255.\n        # use for-loop to get the unique values for each sample\n        vals_list = [len(torch.unique(img_gray[i, :, :, :])) for i in range(b)]\n        vals_list = [2**np.ceil(np.log2(vals)) for vals in vals_list]\n        vals = img_gray.new_tensor(vals_list).view(b, 1, 1, 1)\n        out = torch.poisson(img_gray * vals) / vals\n        noise_gray = out - img_gray\n        noise_gray = noise_gray.expand(b, 3, h, w)\n\n    # always calculate color noise\n    # round and clip image for counting vals correctly\n    img = torch.clamp((img * 255.0).round(), 0, 255) / 255.\n    # use for-loop to get the unique values for each sample\n    vals_list = [len(torch.unique(img[i, :, :, :])) for i in range(b)]\n    vals_list = [2**np.ceil(np.log2(vals)) for vals in vals_list]\n    vals = img.new_tensor(vals_list).view(b, 1, 1, 1)\n    out = torch.poisson(img * vals) / vals\n    noise = out - img\n    if cal_gray_noise:\n        noise = noise * (1 - gray_noise) + noise_gray * gray_noise\n    if not isinstance(scale, (float, int)):\n        scale = scale.view(b, 1, 1, 1)\n    return noise * scale\n\n\ndef add_poisson_noise_pt(img, scale=1.0, clip=True, rounds=False, gray_noise=0):\n    \"\"\"Add poisson noise to a batch of images (PyTorch version).\n\n    Args:\n        img (Tensor): Input image, shape (b, c, h, w), range [0, 1], float32.\n        scale (float | Tensor): Noise scale. Number or Tensor with shape (b).\n            Default: 1.0.\n        gray_noise (float | Tensor): 0-1 number or Tensor with shape (b).\n            0 for False, 1 for True. Default: 0.\n\n    Returns:\n        (Tensor): Returned noisy image, shape (b, c, h, w), range[0, 1],\n            float32.\n    \"\"\"\n    noise = generate_poisson_noise_pt(img, scale, gray_noise)\n    out = img + noise\n    if clip and rounds:\n        out = torch.clamp((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = torch.clamp(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\n# ----------------------- Random Poisson (Shot) Noise ----------------------- #\n\n\ndef random_generate_poisson_noise(img, scale_range=(0, 1.0), gray_prob=0):\n    scale = np.random.uniform(scale_range[0], scale_range[1])\n    if np.random.uniform() < gray_prob:\n        gray_noise = True\n    else:\n        gray_noise = False\n    return generate_poisson_noise(img, scale, gray_noise)\n\n\ndef random_add_poisson_noise(img, scale_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):\n    noise = random_generate_poisson_noise(img, scale_range, gray_prob)\n    out = img + noise\n    if clip and rounds:\n        out = np.clip((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = np.clip(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\ndef random_generate_poisson_noise_pt(img, scale_range=(0, 1.0), gray_prob=0):\n    scale = torch.rand(\n        img.size(0), dtype=img.dtype, device=img.device) * (scale_range[1] - scale_range[0]) + scale_range[0]\n    gray_noise = torch.rand(img.size(0), dtype=img.dtype, device=img.device)\n    gray_noise = (gray_noise < gray_prob).float()\n    return generate_poisson_noise_pt(img, scale, gray_noise)\n\n\ndef random_add_poisson_noise_pt(img, scale_range=(0, 1.0), gray_prob=0, clip=True, rounds=False):\n    noise = random_generate_poisson_noise_pt(img, scale_range, gray_prob)\n    out = img + noise\n    if clip and rounds:\n        out = torch.clamp((out * 255.0).round(), 0, 255) / 255.\n    elif clip:\n        out = torch.clamp(out, 0, 1)\n    elif rounds:\n        out = (out * 255.0).round() / 255.\n    return out\n\n\n# ------------------------------------------------------------------------ #\n# --------------------------- JPEG compression --------------------------- #\n# ------------------------------------------------------------------------ #\n\n\ndef add_jpg_compression(img, quality=90):\n    \"\"\"Add JPG compression artifacts.\n\n    Args:\n        img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.\n        quality (float): JPG compression quality. 0 for lowest quality, 100 for\n            best quality. Default: 90.\n\n    Returns:\n        (Numpy array): Returned image after JPG, shape (h, w, c), range[0, 1],\n            float32.\n    \"\"\"\n    img = np.clip(img, 0, 1)\n    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), quality]\n    _, encimg = cv2.imencode('.jpg', img * 255., encode_param)\n    img = np.float32(cv2.imdecode(encimg, 1)) / 255.\n    return img\n\n\ndef random_add_jpg_compression(img, quality_range=(90, 100)):\n    \"\"\"Randomly add JPG compression artifacts.\n\n    Args:\n        img (Numpy array): Input image, shape (h, w, c), range [0, 1], float32.\n        quality_range (tuple[float] | list[float]): JPG compression quality\n            range. 0 for lowest quality, 100 for best quality.\n            Default: (90, 100).\n\n    Returns:\n        (Numpy array): Returned image after JPG, shape (h, w, c), range[0, 1],\n            float32.\n    \"\"\"\n    quality = np.random.uniform(quality_range[0], quality_range[1])\n    return add_jpg_compression(img, quality)\n"
  },
  {
    "path": "bsr/transforms.py",
    "content": "import cv2\nimport random\nimport torch\n\n\ndef mod_crop(img, scale):\n    \"\"\"Mod crop images, used during testing.\n\n    Args:\n        img (ndarray): Input image.\n        scale (int): Scale factor.\n\n    Returns:\n        ndarray: Result image.\n    \"\"\"\n    img = img.copy()\n    if img.ndim in (2, 3):\n        h, w = img.shape[0], img.shape[1]\n        h_remainder, w_remainder = h % scale, w % scale\n        img = img[:h - h_remainder, :w - w_remainder, ...]\n    else:\n        raise ValueError(f'Wrong img ndim: {img.ndim}.')\n    return img\n\n\ndef paired_random_crop(img_gts, img_lqs, gt_patch_size, scale, gt_path=None):\n    \"\"\"Paired random crop. Support Numpy array and Tensor inputs.\n\n    It crops lists of lq and gt images with corresponding locations.\n\n    Args:\n        img_gts (list[ndarray] | ndarray | list[Tensor] | Tensor): GT images. Note that all images\n            should have the same shape. If the input is an ndarray, it will\n            be transformed to a list containing itself.\n        img_lqs (list[ndarray] | ndarray): LQ images. Note that all images\n            should have the same shape. If the input is an ndarray, it will\n            be transformed to a list containing itself.\n        gt_patch_size (int): GT patch size.\n        scale (int): Scale factor.\n        gt_path (str): Path to ground-truth. Default: None.\n\n    Returns:\n        list[ndarray] | ndarray: GT images and LQ images. If returned results\n            only have one element, just return ndarray.\n    \"\"\"\n\n    if not isinstance(img_gts, list):\n        img_gts = [img_gts]\n    if not isinstance(img_lqs, list):\n        img_lqs = [img_lqs]\n\n    # determine input type: Numpy array or Tensor\n    input_type = 'Tensor' if torch.is_tensor(img_gts[0]) else 'Numpy'\n\n    if input_type == 'Tensor':\n        h_lq, w_lq = img_lqs[0].size()[-2:]\n        h_gt, w_gt = img_gts[0].size()[-2:]\n    else:\n        h_lq, w_lq = img_lqs[0].shape[0:2]\n        h_gt, w_gt = img_gts[0].shape[0:2]\n    lq_patch_size = gt_patch_size // scale\n\n    if h_gt != h_lq * scale or w_gt != w_lq * scale:\n        raise ValueError(f'Scale mismatches. GT ({h_gt}, {w_gt}) is not {scale}x ',\n                         f'multiplication of LQ ({h_lq}, {w_lq}).')\n    if h_lq < lq_patch_size or w_lq < lq_patch_size:\n        raise ValueError(f'LQ ({h_lq}, {w_lq}) is smaller than patch size '\n                         f'({lq_patch_size}, {lq_patch_size}). '\n                         f'Please remove {gt_path}.')\n\n    # randomly choose top and left coordinates for lq patch\n    top = random.randint(0, h_lq - lq_patch_size)\n    left = random.randint(0, w_lq - lq_patch_size)\n\n    # crop lq patch\n    if input_type == 'Tensor':\n        img_lqs = [v[:, :, top:top + lq_patch_size, left:left + lq_patch_size] for v in img_lqs]\n    else:\n        img_lqs = [v[top:top + lq_patch_size, left:left + lq_patch_size, ...] for v in img_lqs]\n\n    # crop corresponding gt patch\n    top_gt, left_gt = int(top * scale), int(left * scale)\n    if input_type == 'Tensor':\n        img_gts = [v[:, :, top_gt:top_gt + gt_patch_size, left_gt:left_gt + gt_patch_size] for v in img_gts]\n    else:\n        img_gts = [v[top_gt:top_gt + gt_patch_size, left_gt:left_gt + gt_patch_size, ...] for v in img_gts]\n    if len(img_gts) == 1:\n        img_gts = img_gts[0]\n    if len(img_lqs) == 1:\n        img_lqs = img_lqs[0]\n    return img_gts, img_lqs\n\n\ndef augment(imgs, hflip=True, rotation=True, flows=None, return_status=False):\n    \"\"\"Augment: horizontal flips OR rotate (0, 90, 180, 270 degrees).\n\n    We use vertical flip and transpose for rotation implementation.\n    All the images in the list use the same augmentation.\n\n    Args:\n        imgs (list[ndarray] | ndarray): Images to be augmented. If the input\n            is an ndarray, it will be transformed to a list.\n        hflip (bool): Horizontal flip. Default: True.\n        rotation (bool): Ratotation. Default: True.\n        flows (list[ndarray]: Flows to be augmented. If the input is an\n            ndarray, it will be transformed to a list.\n            Dimension is (h, w, 2). Default: None.\n        return_status (bool): Return the status of flip and rotation.\n            Default: False.\n\n    Returns:\n        list[ndarray] | ndarray: Augmented images and flows. If returned\n            results only have one element, just return ndarray.\n\n    \"\"\"\n    hflip = hflip and random.random() < 0.5\n    vflip = rotation and random.random() < 0.5\n    rot90 = rotation and random.random() < 0.5\n\n    def _augment(img):\n        if hflip:  # horizontal\n            cv2.flip(img, 1, img)\n        if vflip:  # vertical\n            cv2.flip(img, 0, img)\n        if rot90:\n            img = img.transpose(1, 0, 2)\n        return img\n\n    def _augment_flow(flow):\n        if hflip:  # horizontal\n            cv2.flip(flow, 1, flow)\n            flow[:, :, 0] *= -1\n        if vflip:  # vertical\n            cv2.flip(flow, 0, flow)\n            flow[:, :, 1] *= -1\n        if rot90:\n            flow = flow.transpose(1, 0, 2)\n            flow = flow[:, :, [1, 0]]\n        return flow\n\n    if not isinstance(imgs, list):\n        imgs = [imgs]\n    imgs = [_augment(img) for img in imgs]\n    if len(imgs) == 1:\n        imgs = imgs[0]\n\n    if flows is not None:\n        if not isinstance(flows, list):\n            flows = [flows]\n        flows = [_augment_flow(flow) for flow in flows]\n        if len(flows) == 1:\n            flows = flows[0]\n        return imgs, flows\n    else:\n        if return_status:\n            return imgs, (hflip, vflip, rot90)\n        else:\n            return imgs\n\n\ndef img_rotate(img, angle, center=None, scale=1.0):\n    \"\"\"Rotate image.\n\n    Args:\n        img (ndarray): Image to be rotated.\n        angle (float): Rotation angle in degrees. Positive values mean\n            counter-clockwise rotation.\n        center (tuple[int]): Rotation center. If the center is None,\n            initialize it as the center of the image. Default: None.\n        scale (float): Isotropic scale factor. Default: 1.0.\n    \"\"\"\n    (h, w) = img.shape[:2]\n\n    if center is None:\n        center = (w // 2, h // 2)\n\n    matrix = cv2.getRotationMatrix2D(center, angle, scale)\n    rotated_img = cv2.warpAffine(img, matrix, (w, h))\n    return rotated_img\n"
  },
  {
    "path": "bsr/utils/__init__.py",
    "content": "from .color_util import bgr2ycbcr, rgb2ycbcr, rgb2ycbcr_pt, ycbcr2bgr, ycbcr2rgb\nfrom .diffjpeg import DiffJPEG\nfrom .file_client import FileClient\nfrom .img_process_util import USMSharp, usm_sharp\nfrom .img_util import crop_border, imfrombytes, img2tensor, imwrite, tensor2img\nfrom .logger import AvgTimer, MessageLogger, get_env_info, get_root_logger, init_tb_logger, init_wandb_logger\nfrom .misc import check_resume, get_time_str, make_exp_dirs, mkdir_and_rename, scandir, set_random_seed, sizeof_fmt\nfrom .options import yaml_load\n\n__all__ = [\n    #  color_util.py\n    'bgr2ycbcr',\n    'rgb2ycbcr',\n    'rgb2ycbcr_pt',\n    'ycbcr2bgr',\n    'ycbcr2rgb',\n    # file_client.py\n    'FileClient',\n    # img_util.py\n    'img2tensor',\n    'tensor2img',\n    'imfrombytes',\n    'imwrite',\n    'crop_border',\n    # logger.py\n    'MessageLogger',\n    'AvgTimer',\n    'init_tb_logger',\n    'init_wandb_logger',\n    'get_root_logger',\n    'get_env_info',\n    # misc.py\n    'set_random_seed',\n    'get_time_str',\n    'mkdir_and_rename',\n    'make_exp_dirs',\n    'scandir',\n    'check_resume',\n    'sizeof_fmt',\n    # diffjpeg\n    'DiffJPEG',\n    # img_process_util\n    'USMSharp',\n    'usm_sharp',\n    # options\n    'yaml_load'\n]\n"
  },
  {
    "path": "bsr/utils/color_util.py",
    "content": "import numpy as np\nimport torch\n\n\ndef rgb2ycbcr(img, y_only=False):\n    \"\"\"Convert a RGB image to YCbCr image.\n\n    This function produces the same results as Matlab's `rgb2ycbcr` function.\n    It implements the ITU-R BT.601 conversion for standard-definition\n    television. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.\n\n    It differs from a similar function in cv2.cvtColor: `RGB <-> YCrCb`.\n    In OpenCV, it implements a JPEG conversion. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion.\n\n    Args:\n        img (ndarray): The input image. It accepts:\n            1. np.uint8 type with range [0, 255];\n            2. np.float32 type with range [0, 1].\n        y_only (bool): Whether to only return Y channel. Default: False.\n\n    Returns:\n        ndarray: The converted YCbCr image. The output image has the same type\n            and range as input image.\n    \"\"\"\n    img_type = img.dtype\n    img = _convert_input_type_range(img)\n    if y_only:\n        out_img = np.dot(img, [65.481, 128.553, 24.966]) + 16.0\n    else:\n        out_img = np.matmul(\n            img, [[65.481, -37.797, 112.0], [128.553, -74.203, -93.786], [24.966, 112.0, -18.214]]) + [16, 128, 128]\n    out_img = _convert_output_type_range(out_img, img_type)\n    return out_img\n\n\ndef bgr2ycbcr(img, y_only=False):\n    \"\"\"Convert a BGR image to YCbCr image.\n\n    The bgr version of rgb2ycbcr.\n    It implements the ITU-R BT.601 conversion for standard-definition\n    television. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.\n\n    It differs from a similar function in cv2.cvtColor: `BGR <-> YCrCb`.\n    In OpenCV, it implements a JPEG conversion. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion.\n\n    Args:\n        img (ndarray): The input image. It accepts:\n            1. np.uint8 type with range [0, 255];\n            2. np.float32 type with range [0, 1].\n        y_only (bool): Whether to only return Y channel. Default: False.\n\n    Returns:\n        ndarray: The converted YCbCr image. The output image has the same type\n            and range as input image.\n    \"\"\"\n    img_type = img.dtype\n    img = _convert_input_type_range(img)\n    if y_only:\n        out_img = np.dot(img, [24.966, 128.553, 65.481]) + 16.0\n    else:\n        out_img = np.matmul(\n            img, [[24.966, 112.0, -18.214], [128.553, -74.203, -93.786], [65.481, -37.797, 112.0]]) + [16, 128, 128]\n    out_img = _convert_output_type_range(out_img, img_type)\n    return out_img\n\n\ndef ycbcr2rgb(img):\n    \"\"\"Convert a YCbCr image to RGB image.\n\n    This function produces the same results as Matlab's ycbcr2rgb function.\n    It implements the ITU-R BT.601 conversion for standard-definition\n    television. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.\n\n    It differs from a similar function in cv2.cvtColor: `YCrCb <-> RGB`.\n    In OpenCV, it implements a JPEG conversion. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion.\n\n    Args:\n        img (ndarray): The input image. It accepts:\n            1. np.uint8 type with range [0, 255];\n            2. np.float32 type with range [0, 1].\n\n    Returns:\n        ndarray: The converted RGB image. The output image has the same type\n            and range as input image.\n    \"\"\"\n    img_type = img.dtype\n    img = _convert_input_type_range(img) * 255\n    out_img = np.matmul(img, [[0.00456621, 0.00456621, 0.00456621], [0, -0.00153632, 0.00791071],\n                              [0.00625893, -0.00318811, 0]]) * 255.0 + [-222.921, 135.576, -276.836]  # noqa: E126\n    out_img = _convert_output_type_range(out_img, img_type)\n    return out_img\n\n\ndef ycbcr2bgr(img):\n    \"\"\"Convert a YCbCr image to BGR image.\n\n    The bgr version of ycbcr2rgb.\n    It implements the ITU-R BT.601 conversion for standard-definition\n    television. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.\n\n    It differs from a similar function in cv2.cvtColor: `YCrCb <-> BGR`.\n    In OpenCV, it implements a JPEG conversion. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion.\n\n    Args:\n        img (ndarray): The input image. It accepts:\n            1. np.uint8 type with range [0, 255];\n            2. np.float32 type with range [0, 1].\n\n    Returns:\n        ndarray: The converted BGR image. The output image has the same type\n            and range as input image.\n    \"\"\"\n    img_type = img.dtype\n    img = _convert_input_type_range(img) * 255\n    out_img = np.matmul(img, [[0.00456621, 0.00456621, 0.00456621], [0.00791071, -0.00153632, 0],\n                              [0, -0.00318811, 0.00625893]]) * 255.0 + [-276.836, 135.576, -222.921]  # noqa: E126\n    out_img = _convert_output_type_range(out_img, img_type)\n    return out_img\n\n\ndef _convert_input_type_range(img):\n    \"\"\"Convert the type and range of the input image.\n\n    It converts the input image to np.float32 type and range of [0, 1].\n    It is mainly used for pre-processing the input image in colorspace\n    conversion functions such as rgb2ycbcr and ycbcr2rgb.\n\n    Args:\n        img (ndarray): The input image. It accepts:\n            1. np.uint8 type with range [0, 255];\n            2. np.float32 type with range [0, 1].\n\n    Returns:\n        (ndarray): The converted image with type of np.float32 and range of\n            [0, 1].\n    \"\"\"\n    img_type = img.dtype\n    img = img.astype(np.float32)\n    if img_type == np.float32:\n        pass\n    elif img_type == np.uint8:\n        img /= 255.\n    else:\n        raise TypeError(f'The img type should be np.float32 or np.uint8, but got {img_type}')\n    return img\n\n\ndef _convert_output_type_range(img, dst_type):\n    \"\"\"Convert the type and range of the image according to dst_type.\n\n    It converts the image to desired type and range. If `dst_type` is np.uint8,\n    images will be converted to np.uint8 type with range [0, 255]. If\n    `dst_type` is np.float32, it converts the image to np.float32 type with\n    range [0, 1].\n    It is mainly used for post-processing images in colorspace conversion\n    functions such as rgb2ycbcr and ycbcr2rgb.\n\n    Args:\n        img (ndarray): The image to be converted with np.float32 type and\n            range [0, 255].\n        dst_type (np.uint8 | np.float32): If dst_type is np.uint8, it\n            converts the image to np.uint8 type with range [0, 255]. If\n            dst_type is np.float32, it converts the image to np.float32 type\n            with range [0, 1].\n\n    Returns:\n        (ndarray): The converted image with desired type and range.\n    \"\"\"\n    if dst_type not in (np.uint8, np.float32):\n        raise TypeError(f'The dst_type should be np.float32 or np.uint8, but got {dst_type}')\n    if dst_type == np.uint8:\n        img = img.round()\n    else:\n        img /= 255.\n    return img.astype(dst_type)\n\n\ndef rgb2ycbcr_pt(img, y_only=False):\n    \"\"\"Convert RGB images to YCbCr images (PyTorch version).\n\n    It implements the ITU-R BT.601 conversion for standard-definition television. See more details in\n    https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion.\n\n    Args:\n        img (Tensor): Images with shape (n, 3, h, w), the range [0, 1], float, RGB format.\n         y_only (bool): Whether to only return Y channel. Default: False.\n\n    Returns:\n        (Tensor): converted images with the shape (n, 3/1, h, w), the range [0, 1], float.\n    \"\"\"\n    if y_only:\n        weight = torch.tensor([[65.481], [128.553], [24.966]]).to(img)\n        out_img = torch.matmul(img.permute(0, 2, 3, 1), weight).permute(0, 3, 1, 2) + 16.0\n    else:\n        weight = torch.tensor([[65.481, -37.797, 112.0], [128.553, -74.203, -93.786], [24.966, 112.0, -18.214]]).to(img)\n        bias = torch.tensor([16, 128, 128]).view(1, 3, 1, 1).to(img)\n        out_img = torch.matmul(img.permute(0, 2, 3, 1), weight).permute(0, 3, 1, 2) + bias\n\n    out_img = out_img / 255.\n    return out_img\n"
  },
  {
    "path": "bsr/utils/diffjpeg.py",
    "content": "\"\"\"\nModified from https://github.com/mlomnitz/DiffJPEG\n\nFor images not divisible by 8\nhttps://dsp.stackexchange.com/questions/35339/jpeg-dct-padding/35343#35343\n\"\"\"\nimport itertools\nimport numpy as np\nimport torch\nimport torch.nn as nn\nfrom torch.nn import functional as F\n\n# ------------------------ utils ------------------------#\ny_table = np.array(\n    [[16, 11, 10, 16, 24, 40, 51, 61], [12, 12, 14, 19, 26, 58, 60, 55], [14, 13, 16, 24, 40, 57, 69, 56],\n     [14, 17, 22, 29, 51, 87, 80, 62], [18, 22, 37, 56, 68, 109, 103, 77], [24, 35, 55, 64, 81, 104, 113, 92],\n     [49, 64, 78, 87, 103, 121, 120, 101], [72, 92, 95, 98, 112, 100, 103, 99]],\n    dtype=np.float32).T\ny_table = nn.Parameter(torch.from_numpy(y_table))\nc_table = np.empty((8, 8), dtype=np.float32)\nc_table.fill(99)\nc_table[:4, :4] = np.array([[17, 18, 24, 47], [18, 21, 26, 66], [24, 26, 56, 99], [47, 66, 99, 99]]).T\nc_table = nn.Parameter(torch.from_numpy(c_table))\n\n\ndef diff_round(x):\n    \"\"\" Differentiable rounding function\n    \"\"\"\n    return torch.round(x) + (x - torch.round(x))**3\n\n\ndef quality_to_factor(quality):\n    \"\"\" Calculate factor corresponding to quality\n\n    Args:\n        quality(float): Quality for jpeg compression.\n\n    Returns:\n        float: Compression factor.\n    \"\"\"\n    if quality < 50:\n        quality = 5000. / quality\n    else:\n        quality = 200. - quality * 2\n    return quality / 100.\n\n\n# ------------------------ compression ------------------------#\nclass RGB2YCbCrJpeg(nn.Module):\n    \"\"\" Converts RGB image to YCbCr\n    \"\"\"\n\n    def __init__(self):\n        super(RGB2YCbCrJpeg, self).__init__()\n        matrix = np.array([[0.299, 0.587, 0.114], [-0.168736, -0.331264, 0.5], [0.5, -0.418688, -0.081312]],\n                          dtype=np.float32).T\n        self.shift = nn.Parameter(torch.tensor([0., 128., 128.]))\n        self.matrix = nn.Parameter(torch.from_numpy(matrix))\n\n    def forward(self, image):\n        \"\"\"\n        Args:\n            image(Tensor): batch x 3 x height x width\n\n        Returns:\n            Tensor: batch x height x width x 3\n        \"\"\"\n        image = image.permute(0, 2, 3, 1)\n        result = torch.tensordot(image, self.matrix, dims=1) + self.shift\n        return result.view(image.shape)\n\n\nclass ChromaSubsampling(nn.Module):\n    \"\"\" Chroma subsampling on CbCr channels\n    \"\"\"\n\n    def __init__(self):\n        super(ChromaSubsampling, self).__init__()\n\n    def forward(self, image):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width x 3\n\n        Returns:\n            y(tensor): batch x height x width\n            cb(tensor): batch x height/2 x width/2\n            cr(tensor): batch x height/2 x width/2\n        \"\"\"\n        image_2 = image.permute(0, 3, 1, 2).clone()\n        cb = F.avg_pool2d(image_2[:, 1, :, :].unsqueeze(1), kernel_size=2, stride=(2, 2), count_include_pad=False)\n        cr = F.avg_pool2d(image_2[:, 2, :, :].unsqueeze(1), kernel_size=2, stride=(2, 2), count_include_pad=False)\n        cb = cb.permute(0, 2, 3, 1)\n        cr = cr.permute(0, 2, 3, 1)\n        return image[:, :, :, 0], cb.squeeze(3), cr.squeeze(3)\n\n\nclass BlockSplitting(nn.Module):\n    \"\"\" Splitting image into patches\n    \"\"\"\n\n    def __init__(self):\n        super(BlockSplitting, self).__init__()\n        self.k = 8\n\n    def forward(self, image):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor:  batch x h*w/64 x h x w\n        \"\"\"\n        height, _ = image.shape[1:3]\n        batch_size = image.shape[0]\n        image_reshaped = image.view(batch_size, height // self.k, self.k, -1, self.k)\n        image_transposed = image_reshaped.permute(0, 1, 3, 2, 4)\n        return image_transposed.contiguous().view(batch_size, -1, self.k, self.k)\n\n\nclass DCT8x8(nn.Module):\n    \"\"\" Discrete Cosine Transformation\n    \"\"\"\n\n    def __init__(self):\n        super(DCT8x8, self).__init__()\n        tensor = np.zeros((8, 8, 8, 8), dtype=np.float32)\n        for x, y, u, v in itertools.product(range(8), repeat=4):\n            tensor[x, y, u, v] = np.cos((2 * x + 1) * u * np.pi / 16) * np.cos((2 * y + 1) * v * np.pi / 16)\n        alpha = np.array([1. / np.sqrt(2)] + [1] * 7)\n        self.tensor = nn.Parameter(torch.from_numpy(tensor).float())\n        self.scale = nn.Parameter(torch.from_numpy(np.outer(alpha, alpha) * 0.25).float())\n\n    def forward(self, image):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        image = image - 128\n        result = self.scale * torch.tensordot(image, self.tensor, dims=2)\n        result.view(image.shape)\n        return result\n\n\nclass YQuantize(nn.Module):\n    \"\"\" JPEG Quantization for Y channel\n\n    Args:\n        rounding(function): rounding function to use\n    \"\"\"\n\n    def __init__(self, rounding):\n        super(YQuantize, self).__init__()\n        self.rounding = rounding\n        self.y_table = y_table\n\n    def forward(self, image, factor=1):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        if isinstance(factor, (int, float)):\n            image = image.float() / (self.y_table * factor)\n        else:\n            b = factor.size(0)\n            table = self.y_table.expand(b, 1, 8, 8) * factor.view(b, 1, 1, 1)\n            image = image.float() / table\n        image = self.rounding(image)\n        return image\n\n\nclass CQuantize(nn.Module):\n    \"\"\" JPEG Quantization for CbCr channels\n\n    Args:\n        rounding(function): rounding function to use\n    \"\"\"\n\n    def __init__(self, rounding):\n        super(CQuantize, self).__init__()\n        self.rounding = rounding\n        self.c_table = c_table\n\n    def forward(self, image, factor=1):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        if isinstance(factor, (int, float)):\n            image = image.float() / (self.c_table * factor)\n        else:\n            b = factor.size(0)\n            table = self.c_table.expand(b, 1, 8, 8) * factor.view(b, 1, 1, 1)\n            image = image.float() / table\n        image = self.rounding(image)\n        return image\n\n\nclass CompressJpeg(nn.Module):\n    \"\"\"Full JPEG compression algorithm\n\n    Args:\n        rounding(function): rounding function to use\n    \"\"\"\n\n    def __init__(self, rounding=torch.round):\n        super(CompressJpeg, self).__init__()\n        self.l1 = nn.Sequential(RGB2YCbCrJpeg(), ChromaSubsampling())\n        self.l2 = nn.Sequential(BlockSplitting(), DCT8x8())\n        self.c_quantize = CQuantize(rounding=rounding)\n        self.y_quantize = YQuantize(rounding=rounding)\n\n    def forward(self, image, factor=1):\n        \"\"\"\n        Args:\n            image(tensor): batch x 3 x height x width\n\n        Returns:\n            dict(tensor): Compressed tensor with batch x h*w/64 x 8 x 8.\n        \"\"\"\n        y, cb, cr = self.l1(image * 255)\n        components = {'y': y, 'cb': cb, 'cr': cr}\n        for k in components.keys():\n            comp = self.l2(components[k])\n            if k in ('cb', 'cr'):\n                comp = self.c_quantize(comp, factor=factor)\n            else:\n                comp = self.y_quantize(comp, factor=factor)\n\n            components[k] = comp\n\n        return components['y'], components['cb'], components['cr']\n\n\n# ------------------------ decompression ------------------------#\n\n\nclass YDequantize(nn.Module):\n    \"\"\"Dequantize Y channel\n    \"\"\"\n\n    def __init__(self):\n        super(YDequantize, self).__init__()\n        self.y_table = y_table\n\n    def forward(self, image, factor=1):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        if isinstance(factor, (int, float)):\n            out = image * (self.y_table * factor)\n        else:\n            b = factor.size(0)\n            table = self.y_table.expand(b, 1, 8, 8) * factor.view(b, 1, 1, 1)\n            out = image * table\n        return out\n\n\nclass CDequantize(nn.Module):\n    \"\"\"Dequantize CbCr channel\n    \"\"\"\n\n    def __init__(self):\n        super(CDequantize, self).__init__()\n        self.c_table = c_table\n\n    def forward(self, image, factor=1):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        if isinstance(factor, (int, float)):\n            out = image * (self.c_table * factor)\n        else:\n            b = factor.size(0)\n            table = self.c_table.expand(b, 1, 8, 8) * factor.view(b, 1, 1, 1)\n            out = image * table\n        return out\n\n\nclass iDCT8x8(nn.Module):\n    \"\"\"Inverse discrete Cosine Transformation\n    \"\"\"\n\n    def __init__(self):\n        super(iDCT8x8, self).__init__()\n        alpha = np.array([1. / np.sqrt(2)] + [1] * 7)\n        self.alpha = nn.Parameter(torch.from_numpy(np.outer(alpha, alpha)).float())\n        tensor = np.zeros((8, 8, 8, 8), dtype=np.float32)\n        for x, y, u, v in itertools.product(range(8), repeat=4):\n            tensor[x, y, u, v] = np.cos((2 * u + 1) * x * np.pi / 16) * np.cos((2 * v + 1) * y * np.pi / 16)\n        self.tensor = nn.Parameter(torch.from_numpy(tensor).float())\n\n    def forward(self, image):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        image = image * self.alpha\n        result = 0.25 * torch.tensordot(image, self.tensor, dims=2) + 128\n        result.view(image.shape)\n        return result\n\n\nclass BlockMerging(nn.Module):\n    \"\"\"Merge patches into image\n    \"\"\"\n\n    def __init__(self):\n        super(BlockMerging, self).__init__()\n\n    def forward(self, patches, height, width):\n        \"\"\"\n        Args:\n            patches(tensor) batch x height*width/64, height x width\n            height(int)\n            width(int)\n\n        Returns:\n            Tensor: batch x height x width\n        \"\"\"\n        k = 8\n        batch_size = patches.shape[0]\n        image_reshaped = patches.view(batch_size, height // k, width // k, k, k)\n        image_transposed = image_reshaped.permute(0, 1, 3, 2, 4)\n        return image_transposed.contiguous().view(batch_size, height, width)\n\n\nclass ChromaUpsampling(nn.Module):\n    \"\"\"Upsample chroma layers\n    \"\"\"\n\n    def __init__(self):\n        super(ChromaUpsampling, self).__init__()\n\n    def forward(self, y, cb, cr):\n        \"\"\"\n        Args:\n            y(tensor): y channel image\n            cb(tensor): cb channel\n            cr(tensor): cr channel\n\n        Returns:\n            Tensor: batch x height x width x 3\n        \"\"\"\n\n        def repeat(x, k=2):\n            height, width = x.shape[1:3]\n            x = x.unsqueeze(-1)\n            x = x.repeat(1, 1, k, k)\n            x = x.view(-1, height * k, width * k)\n            return x\n\n        cb = repeat(cb)\n        cr = repeat(cr)\n        return torch.cat([y.unsqueeze(3), cb.unsqueeze(3), cr.unsqueeze(3)], dim=3)\n\n\nclass YCbCr2RGBJpeg(nn.Module):\n    \"\"\"Converts YCbCr image to RGB JPEG\n    \"\"\"\n\n    def __init__(self):\n        super(YCbCr2RGBJpeg, self).__init__()\n\n        matrix = np.array([[1., 0., 1.402], [1, -0.344136, -0.714136], [1, 1.772, 0]], dtype=np.float32).T\n        self.shift = nn.Parameter(torch.tensor([0, -128., -128.]))\n        self.matrix = nn.Parameter(torch.from_numpy(matrix))\n\n    def forward(self, image):\n        \"\"\"\n        Args:\n            image(tensor): batch x height x width x 3\n\n        Returns:\n            Tensor: batch x 3 x height x width\n        \"\"\"\n        result = torch.tensordot(image + self.shift, self.matrix, dims=1)\n        return result.view(image.shape).permute(0, 3, 1, 2)\n\n\nclass DeCompressJpeg(nn.Module):\n    \"\"\"Full JPEG decompression algorithm\n\n    Args:\n        rounding(function): rounding function to use\n    \"\"\"\n\n    def __init__(self, rounding=torch.round):\n        super(DeCompressJpeg, self).__init__()\n        self.c_dequantize = CDequantize()\n        self.y_dequantize = YDequantize()\n        self.idct = iDCT8x8()\n        self.merging = BlockMerging()\n        self.chroma = ChromaUpsampling()\n        self.colors = YCbCr2RGBJpeg()\n\n    def forward(self, y, cb, cr, imgh, imgw, factor=1):\n        \"\"\"\n        Args:\n            compressed(dict(tensor)): batch x h*w/64 x 8 x 8\n            imgh(int)\n            imgw(int)\n            factor(float)\n\n        Returns:\n            Tensor: batch x 3 x height x width\n        \"\"\"\n        components = {'y': y, 'cb': cb, 'cr': cr}\n        for k in components.keys():\n            if k in ('cb', 'cr'):\n                comp = self.c_dequantize(components[k], factor=factor)\n                height, width = int(imgh / 2), int(imgw / 2)\n            else:\n                comp = self.y_dequantize(components[k], factor=factor)\n                height, width = imgh, imgw\n            comp = self.idct(comp)\n            components[k] = self.merging(comp, height, width)\n            #\n        image = self.chroma(components['y'], components['cb'], components['cr'])\n        image = self.colors(image)\n\n        image = torch.min(255 * torch.ones_like(image), torch.max(torch.zeros_like(image), image))\n        return image / 255\n\n\n# ------------------------ main DiffJPEG ------------------------ #\n\n\nclass DiffJPEG(nn.Module):\n    \"\"\"This JPEG algorithm result is slightly different from cv2.\n    DiffJPEG supports batch processing.\n\n    Args:\n        differentiable(bool): If True, uses custom differentiable rounding function, if False, uses standard torch.round\n    \"\"\"\n\n    def __init__(self, differentiable=True):\n        super(DiffJPEG, self).__init__()\n        if differentiable:\n            rounding = diff_round\n        else:\n            rounding = torch.round\n\n        self.compress = CompressJpeg(rounding=rounding)\n        self.decompress = DeCompressJpeg(rounding=rounding)\n\n    def forward(self, x, quality):\n        \"\"\"\n        Args:\n            x (Tensor): Input image, bchw, rgb, [0, 1]\n            quality(float): Quality factor for jpeg compression scheme.\n        \"\"\"\n        factor = quality\n        if isinstance(factor, (int, float)):\n            factor = quality_to_factor(factor)\n        else:\n            for i in range(factor.size(0)):\n                factor[i] = quality_to_factor(factor[i])\n        h, w = x.size()[-2:]\n        h_pad, w_pad = 0, 0\n        # why should use 16\n        if h % 16 != 0:\n            h_pad = 16 - h % 16\n        if w % 16 != 0:\n            w_pad = 16 - w % 16\n        x = F.pad(x, (0, w_pad, 0, h_pad), mode='constant', value=0)\n\n        y, cb, cr = self.compress(x, factor=factor)\n        recovered = self.decompress(y, cb, cr, (h + h_pad), (w + w_pad), factor=factor)\n        recovered = recovered[:, :, 0:h, 0:w]\n        return recovered\n\n\nif __name__ == '__main__':\n    import cv2\n\n    from bsr.utils import img2tensor, tensor2img\n\n    img_gt = cv2.imread('test.png') / 255.\n\n    # -------------- cv2 -------------- #\n    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 20]\n    _, encimg = cv2.imencode('.jpg', img_gt * 255., encode_param)\n    img_lq = np.float32(cv2.imdecode(encimg, 1))\n    cv2.imwrite('cv2_JPEG_20.png', img_lq)\n\n    # -------------- DiffJPEG -------------- #\n    jpeger = DiffJPEG(differentiable=False).cuda()\n    img_gt = img2tensor(img_gt)\n    img_gt = torch.stack([img_gt, img_gt]).cuda()\n    quality = img_gt.new_tensor([20, 40])\n    out = jpeger(img_gt, quality=quality)\n\n    cv2.imwrite('pt_JPEG_20.png', tensor2img(out[0]))\n    cv2.imwrite('pt_JPEG_40.png', tensor2img(out[1]))\n"
  },
  {
    "path": "bsr/utils/dist_util.py",
    "content": "# Modified from https://github.com/open-mmlab/mmcv/blob/master/mmcv/runner/dist_utils.py  # noqa: E501\nimport functools\nimport os\nimport subprocess\nimport torch\nimport torch.distributed as dist\nimport torch.multiprocessing as mp\n\n\ndef init_dist(launcher, backend='nccl', **kwargs):\n    if mp.get_start_method(allow_none=True) is None:\n        mp.set_start_method('spawn')\n    if launcher == 'pytorch':\n        _init_dist_pytorch(backend, **kwargs)\n    elif launcher == 'slurm':\n        _init_dist_slurm(backend, **kwargs)\n    else:\n        raise ValueError(f'Invalid launcher type: {launcher}')\n\n\ndef _init_dist_pytorch(backend, **kwargs):\n    rank = int(os.environ['RANK'])\n    num_gpus = torch.cuda.device_count()\n    torch.cuda.set_device(rank % num_gpus)\n    dist.init_process_group(backend=backend, **kwargs)\n\n\ndef _init_dist_slurm(backend, port=None):\n    \"\"\"Initialize slurm distributed training environment.\n\n    If argument ``port`` is not specified, then the master port will be system\n    environment variable ``MASTER_PORT``. If ``MASTER_PORT`` is not in system\n    environment variable, then a default port ``29500`` will be used.\n\n    Args:\n        backend (str): Backend of torch.distributed.\n        port (int, optional): Master port. Defaults to None.\n    \"\"\"\n    proc_id = int(os.environ['SLURM_PROCID'])\n    ntasks = int(os.environ['SLURM_NTASKS'])\n    node_list = os.environ['SLURM_NODELIST']\n    num_gpus = torch.cuda.device_count()\n    torch.cuda.set_device(proc_id % num_gpus)\n    addr = subprocess.getoutput(f'scontrol show hostname {node_list} | head -n1')\n    # specify master port\n    if port is not None:\n        os.environ['MASTER_PORT'] = str(port)\n    elif 'MASTER_PORT' in os.environ:\n        pass  # use MASTER_PORT in the environment variable\n    else:\n        # 29500 is torch.distributed default port\n        os.environ['MASTER_PORT'] = '29500'\n    os.environ['MASTER_ADDR'] = addr\n    os.environ['WORLD_SIZE'] = str(ntasks)\n    os.environ['LOCAL_RANK'] = str(proc_id % num_gpus)\n    os.environ['RANK'] = str(proc_id)\n    dist.init_process_group(backend=backend)\n\n\ndef get_dist_info():\n    if dist.is_available():\n        initialized = dist.is_initialized()\n    else:\n        initialized = False\n    if initialized:\n        rank = dist.get_rank()\n        world_size = dist.get_world_size()\n    else:\n        rank = 0\n        world_size = 1\n    return rank, world_size\n\n\ndef master_only(func):\n\n    @functools.wraps(func)\n    def wrapper(*args, **kwargs):\n        rank, _ = get_dist_info()\n        if rank == 0:\n            return func(*args, **kwargs)\n\n    return wrapper\n"
  },
  {
    "path": "bsr/utils/download_util.py",
    "content": "import math\nimport os\nimport requests\nfrom torch.hub import download_url_to_file, get_dir\nfrom tqdm import tqdm\nfrom urllib.parse import urlparse\n\nfrom .misc import sizeof_fmt\n\n\ndef download_file_from_google_drive(file_id, save_path):\n    \"\"\"Download files from google drive.\n\n    Reference: https://stackoverflow.com/questions/25010369/wget-curl-large-file-from-google-drive\n\n    Args:\n        file_id (str): File id.\n        save_path (str): Save path.\n    \"\"\"\n\n    session = requests.Session()\n    URL = 'https://docs.google.com/uc?export=download'\n    params = {'id': file_id}\n\n    response = session.get(URL, params=params, stream=True)\n    token = get_confirm_token(response)\n    if token:\n        params['confirm'] = token\n        response = session.get(URL, params=params, stream=True)\n\n    # get file size\n    response_file_size = session.get(URL, params=params, stream=True, headers={'Range': 'bytes=0-2'})\n    if 'Content-Range' in response_file_size.headers:\n        file_size = int(response_file_size.headers['Content-Range'].split('/')[1])\n    else:\n        file_size = None\n\n    save_response_content(response, save_path, file_size)\n\n\ndef get_confirm_token(response):\n    for key, value in response.cookies.items():\n        if key.startswith('download_warning'):\n            return value\n    return None\n\n\ndef save_response_content(response, destination, file_size=None, chunk_size=32768):\n    if file_size is not None:\n        pbar = tqdm(total=math.ceil(file_size / chunk_size), unit='chunk')\n\n        readable_file_size = sizeof_fmt(file_size)\n    else:\n        pbar = None\n\n    with open(destination, 'wb') as f:\n        downloaded_size = 0\n        for chunk in response.iter_content(chunk_size):\n            downloaded_size += chunk_size\n            if pbar is not None:\n                pbar.update(1)\n                pbar.set_description(f'Download {sizeof_fmt(downloaded_size)} / {readable_file_size}')\n            if chunk:  # filter out keep-alive new chunks\n                f.write(chunk)\n        if pbar is not None:\n            pbar.close()\n\n\ndef load_file_from_url(url, model_dir=None, progress=True, file_name=None):\n    \"\"\"Load file form http url, will download models if necessary.\n\n    Reference: https://github.com/1adrianb/face-alignment/blob/master/face_alignment/utils.py\n\n    Args:\n        url (str): URL to be downloaded.\n        model_dir (str): The path to save the downloaded model. Should be a full path. If None, use pytorch hub_dir.\n            Default: None.\n        progress (bool): Whether to show the download progress. Default: True.\n        file_name (str): The downloaded file name. If None, use the file name in the url. Default: None.\n\n    Returns:\n        str: The path to the downloaded file.\n    \"\"\"\n    if model_dir is None:  # use the pytorch hub_dir\n        hub_dir = get_dir()\n        model_dir = os.path.join(hub_dir, 'checkpoints')\n\n    os.makedirs(model_dir, exist_ok=True)\n\n    parts = urlparse(url)\n    filename = os.path.basename(parts.path)\n    if file_name is not None:\n        filename = file_name\n    cached_file = os.path.abspath(os.path.join(model_dir, filename))\n    if not os.path.exists(cached_file):\n        print(f'Downloading: \"{url}\" to {cached_file}\\n')\n        download_url_to_file(url, cached_file, hash_prefix=None, progress=progress)\n    return cached_file\n"
  },
  {
    "path": "bsr/utils/file_client.py",
    "content": "# Modified from https://github.com/open-mmlab/mmcv/blob/master/mmcv/fileio/file_client.py  # noqa: E501\nfrom abc import ABCMeta, abstractmethod\n\n\nclass BaseStorageBackend(metaclass=ABCMeta):\n    \"\"\"Abstract class of storage backends.\n\n    All backends need to implement two apis: ``get()`` and ``get_text()``.\n    ``get()`` reads the file as a byte stream and ``get_text()`` reads the file\n    as texts.\n    \"\"\"\n\n    @abstractmethod\n    def get(self, filepath):\n        pass\n\n    @abstractmethod\n    def get_text(self, filepath):\n        pass\n\n\nclass MemcachedBackend(BaseStorageBackend):\n    \"\"\"Memcached storage backend.\n\n    Attributes:\n        server_list_cfg (str): Config file for memcached server list.\n        client_cfg (str): Config file for memcached client.\n        sys_path (str | None): Additional path to be appended to `sys.path`.\n            Default: None.\n    \"\"\"\n\n    def __init__(self, server_list_cfg, client_cfg, sys_path=None):\n        if sys_path is not None:\n            import sys\n            sys.path.append(sys_path)\n        try:\n            import mc\n        except ImportError:\n            raise ImportError('Please install memcached to enable MemcachedBackend.')\n\n        self.server_list_cfg = server_list_cfg\n        self.client_cfg = client_cfg\n        self._client = mc.MemcachedClient.GetInstance(self.server_list_cfg, self.client_cfg)\n        # mc.pyvector servers as a point which points to a memory cache\n        self._mc_buffer = mc.pyvector()\n\n    def get(self, filepath):\n        filepath = str(filepath)\n        import mc\n        self._client.Get(filepath, self._mc_buffer)\n        value_buf = mc.ConvertBuffer(self._mc_buffer)\n        return value_buf\n\n    def get_text(self, filepath):\n        raise NotImplementedError\n\n\nclass HardDiskBackend(BaseStorageBackend):\n    \"\"\"Raw hard disks storage backend.\"\"\"\n\n    def get(self, filepath):\n        filepath = str(filepath)\n        with open(filepath, 'rb') as f:\n            value_buf = f.read()\n        return value_buf\n\n    def get_text(self, filepath):\n        filepath = str(filepath)\n        with open(filepath, 'r') as f:\n            value_buf = f.read()\n        return value_buf\n\n\nclass LmdbBackend(BaseStorageBackend):\n    \"\"\"Lmdb storage backend.\n\n    Args:\n        db_paths (str | list[str]): Lmdb database paths.\n        client_keys (str | list[str]): Lmdb client keys. Default: 'default'.\n        readonly (bool, optional): Lmdb environment parameter. If True,\n            disallow any write operations. Default: True.\n        lock (bool, optional): Lmdb environment parameter. If False, when\n            concurrent access occurs, do not lock the database. Default: False.\n        readahead (bool, optional): Lmdb environment parameter. If False,\n            disable the OS filesystem readahead mechanism, which may improve\n            random read performance when a database is larger than RAM.\n            Default: False.\n\n    Attributes:\n        db_paths (list): Lmdb database path.\n        _client (list): A list of several lmdb envs.\n    \"\"\"\n\n    def __init__(self, db_paths, client_keys='default', readonly=True, lock=False, readahead=False, **kwargs):\n        try:\n            import lmdb\n        except ImportError:\n            raise ImportError('Please install lmdb to enable LmdbBackend.')\n\n        if isinstance(client_keys, str):\n            client_keys = [client_keys]\n\n        if isinstance(db_paths, list):\n            self.db_paths = [str(v) for v in db_paths]\n        elif isinstance(db_paths, str):\n            self.db_paths = [str(db_paths)]\n        assert len(client_keys) == len(self.db_paths), ('client_keys and db_paths should have the same length, '\n                                                        f'but received {len(client_keys)} and {len(self.db_paths)}.')\n\n        self._client = {}\n        for client, path in zip(client_keys, self.db_paths):\n            self._client[client] = lmdb.open(path, readonly=readonly, lock=lock, readahead=readahead, **kwargs)\n\n    def get(self, filepath, client_key):\n        \"\"\"Get values according to the filepath from one lmdb named client_key.\n\n        Args:\n            filepath (str | obj:`Path`): Here, filepath is the lmdb key.\n            client_key (str): Used for distinguishing different lmdb envs.\n        \"\"\"\n        filepath = str(filepath)\n        assert client_key in self._client, (f'client_key {client_key} is not in lmdb clients.')\n        client = self._client[client_key]\n        with client.begin(write=False) as txn:\n            value_buf = txn.get(filepath.encode('ascii'))\n        return value_buf\n\n    def get_text(self, filepath):\n        raise NotImplementedError\n\n\nclass FileClient(object):\n    \"\"\"A general file client to access files in different backend.\n\n    The client loads a file or text in a specified backend from its path\n    and return it as a binary file. it can also register other backend\n    accessor with a given name and backend class.\n\n    Attributes:\n        backend (str): The storage backend type. Options are \"disk\",\n            \"memcached\" and \"lmdb\".\n        client (:obj:`BaseStorageBackend`): The backend object.\n    \"\"\"\n\n    _backends = {\n        'disk': HardDiskBackend,\n        'memcached': MemcachedBackend,\n        'lmdb': LmdbBackend,\n    }\n\n    def __init__(self, backend='disk', **kwargs):\n        if backend not in self._backends:\n            raise ValueError(f'Backend {backend} is not supported. Currently supported ones'\n                             f' are {list(self._backends.keys())}')\n        self.backend = backend\n        self.client = self._backends[backend](**kwargs)\n\n    def get(self, filepath, client_key='default'):\n        # client_key is used only for lmdb, where different fileclients have\n        # different lmdb environments.\n        if self.backend == 'lmdb':\n            return self.client.get(filepath, client_key)\n        else:\n            return self.client.get(filepath)\n\n    def get_text(self, filepath):\n        return self.client.get_text(filepath)\n"
  },
  {
    "path": "bsr/utils/flow_util.py",
    "content": "# Modified from https://github.com/open-mmlab/mmcv/blob/master/mmcv/video/optflow.py  # noqa: E501\nimport cv2\nimport numpy as np\nimport os\n\n\ndef flowread(flow_path, quantize=False, concat_axis=0, *args, **kwargs):\n    \"\"\"Read an optical flow map.\n\n    Args:\n        flow_path (ndarray or str): Flow path.\n        quantize (bool): whether to read quantized pair, if set to True,\n            remaining args will be passed to :func:`dequantize_flow`.\n        concat_axis (int): The axis that dx and dy are concatenated,\n            can be either 0 or 1. Ignored if quantize is False.\n\n    Returns:\n        ndarray: Optical flow represented as a (h, w, 2) numpy array\n    \"\"\"\n    if quantize:\n        assert concat_axis in [0, 1]\n        cat_flow = cv2.imread(flow_path, cv2.IMREAD_UNCHANGED)\n        if cat_flow.ndim != 2:\n            raise IOError(f'{flow_path} is not a valid quantized flow file, its dimension is {cat_flow.ndim}.')\n        assert cat_flow.shape[concat_axis] % 2 == 0\n        dx, dy = np.split(cat_flow, 2, axis=concat_axis)\n        flow = dequantize_flow(dx, dy, *args, **kwargs)\n    else:\n        with open(flow_path, 'rb') as f:\n            try:\n                header = f.read(4).decode('utf-8')\n            except Exception:\n                raise IOError(f'Invalid flow file: {flow_path}')\n            else:\n                if header != 'PIEH':\n                    raise IOError(f'Invalid flow file: {flow_path}, header does not contain PIEH')\n\n            w = np.fromfile(f, np.int32, 1).squeeze()\n            h = np.fromfile(f, np.int32, 1).squeeze()\n            flow = np.fromfile(f, np.float32, w * h * 2).reshape((h, w, 2))\n\n    return flow.astype(np.float32)\n\n\ndef flowwrite(flow, filename, quantize=False, concat_axis=0, *args, **kwargs):\n    \"\"\"Write optical flow to file.\n\n    If the flow is not quantized, it will be saved as a .flo file losslessly,\n    otherwise a jpeg image which is lossy but of much smaller size. (dx and dy\n    will be concatenated horizontally into a single image if quantize is True.)\n\n    Args:\n        flow (ndarray): (h, w, 2) array of optical flow.\n        filename (str): Output filepath.\n        quantize (bool): Whether to quantize the flow and save it to 2 jpeg\n            images. If set to True, remaining args will be passed to\n            :func:`quantize_flow`.\n        concat_axis (int): The axis that dx and dy are concatenated,\n            can be either 0 or 1. Ignored if quantize is False.\n    \"\"\"\n    if not quantize:\n        with open(filename, 'wb') as f:\n            f.write('PIEH'.encode('utf-8'))\n            np.array([flow.shape[1], flow.shape[0]], dtype=np.int32).tofile(f)\n            flow = flow.astype(np.float32)\n            flow.tofile(f)\n            f.flush()\n    else:\n        assert concat_axis in [0, 1]\n        dx, dy = quantize_flow(flow, *args, **kwargs)\n        dxdy = np.concatenate((dx, dy), axis=concat_axis)\n        os.makedirs(os.path.dirname(filename), exist_ok=True)\n        cv2.imwrite(filename, dxdy)\n\n\ndef quantize_flow(flow, max_val=0.02, norm=True):\n    \"\"\"Quantize flow to [0, 255].\n\n    After this step, the size of flow will be much smaller, and can be\n    dumped as jpeg images.\n\n    Args:\n        flow (ndarray): (h, w, 2) array of optical flow.\n        max_val (float): Maximum value of flow, values beyond\n                        [-max_val, max_val] will be truncated.\n        norm (bool): Whether to divide flow values by image width/height.\n\n    Returns:\n        tuple[ndarray]: Quantized dx and dy.\n    \"\"\"\n    h, w, _ = flow.shape\n    dx = flow[..., 0]\n    dy = flow[..., 1]\n    if norm:\n        dx = dx / w  # avoid inplace operations\n        dy = dy / h\n    # use 255 levels instead of 256 to make sure 0 is 0 after dequantization.\n    flow_comps = [quantize(d, -max_val, max_val, 255, np.uint8) for d in [dx, dy]]\n    return tuple(flow_comps)\n\n\ndef dequantize_flow(dx, dy, max_val=0.02, denorm=True):\n    \"\"\"Recover from quantized flow.\n\n    Args:\n        dx (ndarray): Quantized dx.\n        dy (ndarray): Quantized dy.\n        max_val (float): Maximum value used when quantizing.\n        denorm (bool): Whether to multiply flow values with width/height.\n\n    Returns:\n        ndarray: Dequantized flow.\n    \"\"\"\n    assert dx.shape == dy.shape\n    assert dx.ndim == 2 or (dx.ndim == 3 and dx.shape[-1] == 1)\n\n    dx, dy = [dequantize(d, -max_val, max_val, 255) for d in [dx, dy]]\n\n    if denorm:\n        dx *= dx.shape[1]\n        dy *= dx.shape[0]\n    flow = np.dstack((dx, dy))\n    return flow\n\n\ndef quantize(arr, min_val, max_val, levels, dtype=np.int64):\n    \"\"\"Quantize an array of (-inf, inf) to [0, levels-1].\n\n    Args:\n        arr (ndarray): Input array.\n        min_val (scalar): Minimum value to be clipped.\n        max_val (scalar): Maximum value to be clipped.\n        levels (int): Quantization levels.\n        dtype (np.type): The type of the quantized array.\n\n    Returns:\n        tuple: Quantized array.\n    \"\"\"\n    if not (isinstance(levels, int) and levels > 1):\n        raise ValueError(f'levels must be a positive integer, but got {levels}')\n    if min_val >= max_val:\n        raise ValueError(f'min_val ({min_val}) must be smaller than max_val ({max_val})')\n\n    arr = np.clip(arr, min_val, max_val) - min_val\n    quantized_arr = np.minimum(np.floor(levels * arr / (max_val - min_val)).astype(dtype), levels - 1)\n\n    return quantized_arr\n\n\ndef dequantize(arr, min_val, max_val, levels, dtype=np.float64):\n    \"\"\"Dequantize an array.\n\n    Args:\n        arr (ndarray): Input array.\n        min_val (scalar): Minimum value to be clipped.\n        max_val (scalar): Maximum value to be clipped.\n        levels (int): Quantization levels.\n        dtype (np.type): The type of the dequantized array.\n\n    Returns:\n        tuple: Dequantized array.\n    \"\"\"\n    if not (isinstance(levels, int) and levels > 1):\n        raise ValueError(f'levels must be a positive integer, but got {levels}')\n    if min_val >= max_val:\n        raise ValueError(f'min_val ({min_val}) must be smaller than max_val ({max_val})')\n\n    dequantized_arr = (arr + 0.5).astype(dtype) * (max_val - min_val) / levels + min_val\n\n    return dequantized_arr\n"
  },
  {
    "path": "bsr/utils/img_process_util.py",
    "content": "import cv2\nimport numpy as np\nimport torch\nfrom torch.nn import functional as F\n\n\ndef filter2D(img, kernel):\n    \"\"\"PyTorch version of cv2.filter2D\n\n    Args:\n        img (Tensor): (b, c, h, w)\n        kernel (Tensor): (b, k, k)\n    \"\"\"\n    k = kernel.size(-1)\n    b, c, h, w = img.size()\n    if k % 2 == 1:\n        img = F.pad(img, (k // 2, k // 2, k // 2, k // 2), mode='reflect')\n    else:\n        raise ValueError('Wrong kernel size')\n\n    ph, pw = img.size()[-2:]\n\n    if kernel.size(0) == 1:\n        # apply the same kernel to all batch images\n        img = img.view(b * c, 1, ph, pw)\n        kernel = kernel.view(1, 1, k, k)\n        return F.conv2d(img, kernel, padding=0).view(b, c, h, w)\n    else:\n        img = img.view(1, b * c, ph, pw)\n        kernel = kernel.view(b, 1, k, k).repeat(1, c, 1, 1).view(b * c, 1, k, k)\n        return F.conv2d(img, kernel, groups=b * c).view(b, c, h, w)\n\n\ndef usm_sharp(img, weight=0.5, radius=50, threshold=10):\n    \"\"\"USM sharpening.\n\n    Input image: I; Blurry image: B.\n    1. sharp = I + weight * (I - B)\n    2. Mask = 1 if abs(I - B) > threshold, else: 0\n    3. Blur mask:\n    4. Out = Mask * sharp + (1 - Mask) * I\n\n\n    Args:\n        img (Numpy array): Input image, HWC, BGR; float32, [0, 1].\n        weight (float): Sharp weight. Default: 1.\n        radius (float): Kernel size of Gaussian blur. Default: 50.\n        threshold (int):\n    \"\"\"\n    if radius % 2 == 0:\n        radius += 1\n    blur = cv2.GaussianBlur(img, (radius, radius), 0)\n    residual = img - blur\n    mask = np.abs(residual) * 255 > threshold\n    mask = mask.astype('float32')\n    soft_mask = cv2.GaussianBlur(mask, (radius, radius), 0)\n\n    sharp = img + weight * residual\n    sharp = np.clip(sharp, 0, 1)\n    return soft_mask * sharp + (1 - soft_mask) * img\n\n\nclass USMSharp(torch.nn.Module):\n\n    def __init__(self, radius=50, sigma=0):\n        super(USMSharp, self).__init__()\n        if radius % 2 == 0:\n            radius += 1\n        self.radius = radius\n        kernel = cv2.getGaussianKernel(radius, sigma)\n        kernel = torch.FloatTensor(np.dot(kernel, kernel.transpose())).unsqueeze_(0)\n        self.register_buffer('kernel', kernel)\n\n    def forward(self, img, weight=0.5, threshold=10):\n        blur = filter2D(img, self.kernel)\n        residual = img - blur\n\n        mask = torch.abs(residual) * 255 > threshold\n        mask = mask.float()\n        soft_mask = filter2D(mask, self.kernel)\n        sharp = img + weight * residual\n        sharp = torch.clip(sharp, 0, 1)\n        return soft_mask * sharp + (1 - soft_mask) * img\n"
  },
  {
    "path": "bsr/utils/img_util.py",
    "content": "import cv2\nimport math\nimport numpy as np\nimport os\nimport torch\nfrom torchvision.utils import make_grid\n\n\ndef img2tensor(imgs, bgr2rgb=True, float32=True):\n    \"\"\"Numpy array to tensor.\n\n    Args:\n        imgs (list[ndarray] | ndarray): Input images.\n        bgr2rgb (bool): Whether to change bgr to rgb.\n        float32 (bool): Whether to change to float32.\n\n    Returns:\n        list[tensor] | tensor: Tensor images. If returned results only have\n            one element, just return tensor.\n    \"\"\"\n\n    def _totensor(img, bgr2rgb, float32):\n        if img.shape[2] == 3 and bgr2rgb:\n            if img.dtype == 'float64':\n                img = img.astype('float32')\n            img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        img = torch.from_numpy(img.transpose(2, 0, 1))\n        if float32:\n            img = img.float()\n        return img\n\n    if isinstance(imgs, list):\n        return [_totensor(img, bgr2rgb, float32) for img in imgs]\n    else:\n        return _totensor(imgs, bgr2rgb, float32)\n\n\ndef tensor2img(tensor, rgb2bgr=True, out_type=np.uint8, min_max=(0, 1)):\n    \"\"\"Convert torch Tensors into image numpy arrays.\n\n    After clamping to [min, max], values will be normalized to [0, 1].\n\n    Args:\n        tensor (Tensor or list[Tensor]): Accept shapes:\n            1) 4D mini-batch Tensor of shape (B x 3/1 x H x W);\n            2) 3D Tensor of shape (3/1 x H x W);\n            3) 2D Tensor of shape (H x W).\n            Tensor channel should be in RGB order.\n        rgb2bgr (bool): Whether to change rgb to bgr.\n        out_type (numpy type): output types. If ``np.uint8``, transform outputs\n            to uint8 type with range [0, 255]; otherwise, float type with\n            range [0, 1]. Default: ``np.uint8``.\n        min_max (tuple[int]): min and max values for clamp.\n\n    Returns:\n        (Tensor or list): 3D ndarray of shape (H x W x C) OR 2D ndarray of\n        shape (H x W). The channel order is BGR.\n    \"\"\"\n    if not (torch.is_tensor(tensor) or (isinstance(tensor, list) and all(torch.is_tensor(t) for t in tensor))):\n        raise TypeError(f'tensor or list of tensors expected, got {type(tensor)}')\n\n    if torch.is_tensor(tensor):\n        tensor = [tensor]\n    result = []\n    for _tensor in tensor:\n        _tensor = _tensor.squeeze(0).float().detach().cpu().clamp_(*min_max)\n        _tensor = (_tensor - min_max[0]) / (min_max[1] - min_max[0])\n\n        n_dim = _tensor.dim()\n        if n_dim == 4:\n            img_np = make_grid(_tensor, nrow=int(math.sqrt(_tensor.size(0))), normalize=False).numpy()\n            img_np = img_np.transpose(1, 2, 0)\n            if rgb2bgr:\n                img_np = cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR)\n        elif n_dim == 3:\n            img_np = _tensor.numpy()\n            img_np = img_np.transpose(1, 2, 0)\n            if img_np.shape[2] == 1:  # gray image\n                img_np = np.squeeze(img_np, axis=2)\n            else:\n                if rgb2bgr:\n                    img_np = cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR)\n        elif n_dim == 2:\n            img_np = _tensor.numpy()\n        else:\n            raise TypeError(f'Only support 4D, 3D or 2D tensor. But received with dimension: {n_dim}')\n        if out_type == np.uint8:\n            # Unlike MATLAB, numpy.unit8() WILL NOT round by default.\n            img_np = (img_np * 255.0).round()\n        img_np = img_np.astype(out_type)\n        result.append(img_np)\n    if len(result) == 1:\n        result = result[0]\n    return result\n\n\ndef tensor2img_fast(tensor, rgb2bgr=True, min_max=(0, 1)):\n    \"\"\"This implementation is slightly faster than tensor2img.\n    It now only supports torch tensor with shape (1, c, h, w).\n\n    Args:\n        tensor (Tensor): Now only support torch tensor with (1, c, h, w).\n        rgb2bgr (bool): Whether to change rgb to bgr. Default: True.\n        min_max (tuple[int]): min and max values for clamp.\n    \"\"\"\n    output = tensor.squeeze(0).detach().clamp_(*min_max).permute(1, 2, 0)\n    output = (output - min_max[0]) / (min_max[1] - min_max[0]) * 255\n    output = output.type(torch.uint8).cpu().numpy()\n    if rgb2bgr:\n        output = cv2.cvtColor(output, cv2.COLOR_RGB2BGR)\n    return output\n\n\ndef imfrombytes(content, flag='color', float32=False):\n    \"\"\"Read an image from bytes.\n\n    Args:\n        content (bytes): Image bytes got from files or other streams.\n        flag (str): Flags specifying the color type of a loaded image,\n            candidates are `color`, `grayscale` and `unchanged`.\n        float32 (bool): Whether to change to float32., If True, will also norm\n            to [0, 1]. Default: False.\n\n    Returns:\n        ndarray: Loaded image array.\n    \"\"\"\n    img_np = np.frombuffer(content, np.uint8)\n    imread_flags = {'color': cv2.IMREAD_COLOR, 'grayscale': cv2.IMREAD_GRAYSCALE, 'unchanged': cv2.IMREAD_UNCHANGED}\n    img = cv2.imdecode(img_np, imread_flags[flag])\n    if float32:\n        img = img.astype(np.float32) / 255.\n    return img\n\n\ndef imwrite(img, file_path, params=None, auto_mkdir=True):\n    \"\"\"Write image to file.\n\n    Args:\n        img (ndarray): Image array to be written.\n        file_path (str): Image file path.\n        params (None or list): Same as opencv's :func:`imwrite` interface.\n        auto_mkdir (bool): If the parent folder of `file_path` does not exist,\n            whether to create it automatically.\n\n    Returns:\n        bool: Successful or not.\n    \"\"\"\n    if auto_mkdir:\n        dir_name = os.path.abspath(os.path.dirname(file_path))\n        os.makedirs(dir_name, exist_ok=True)\n    ok = cv2.imwrite(file_path, img, params)\n    if not ok:\n        raise IOError('Failed in writing images.')\n\n\ndef crop_border(imgs, crop_border):\n    \"\"\"Crop borders of images.\n\n    Args:\n        imgs (list[ndarray] | ndarray): Images with shape (h, w, c).\n        crop_border (int): Crop border for each end of height and weight.\n\n    Returns:\n        list[ndarray]: Cropped images.\n    \"\"\"\n    if crop_border == 0:\n        return imgs\n    else:\n        if isinstance(imgs, list):\n            return [v[crop_border:-crop_border, crop_border:-crop_border, ...] for v in imgs]\n        else:\n            return imgs[crop_border:-crop_border, crop_border:-crop_border, ...]\n"
  },
  {
    "path": "bsr/utils/lmdb_util.py",
    "content": "import cv2\nimport lmdb\nimport sys\nfrom multiprocessing import Pool\nfrom os import path as osp\nfrom tqdm import tqdm\n\n\ndef make_lmdb_from_imgs(data_path,\n                        lmdb_path,\n                        img_path_list,\n                        keys,\n                        batch=5000,\n                        compress_level=1,\n                        multiprocessing_read=False,\n                        n_thread=40,\n                        map_size=None):\n    \"\"\"Make lmdb from images.\n\n    Contents of lmdb. The file structure is:\n\n    ::\n\n        example.lmdb\n        ├── data.mdb\n        ├── lock.mdb\n        ├── meta_info.txt\n\n    The data.mdb and lock.mdb are standard lmdb files and you can refer to\n    https://lmdb.readthedocs.io/en/release/ for more details.\n\n    The meta_info.txt is a specified txt file to record the meta information\n    of our datasets. It will be automatically created when preparing\n    datasets by our provided dataset tools.\n    Each line in the txt file records 1)image name (with extension),\n    2)image shape, and 3)compression level, separated by a white space.\n\n    For example, the meta information could be:\n    `000_00000000.png (720,1280,3) 1`, which means:\n    1) image name (with extension): 000_00000000.png;\n    2) image shape: (720,1280,3);\n    3) compression level: 1\n\n    We use the image name without extension as the lmdb key.\n\n    If `multiprocessing_read` is True, it will read all the images to memory\n    using multiprocessing. Thus, your server needs to have enough memory.\n\n    Args:\n        data_path (str): Data path for reading images.\n        lmdb_path (str): Lmdb save path.\n        img_path_list (str): Image path list.\n        keys (str): Used for lmdb keys.\n        batch (int): After processing batch images, lmdb commits.\n            Default: 5000.\n        compress_level (int): Compress level when encoding images. Default: 1.\n        multiprocessing_read (bool): Whether use multiprocessing to read all\n            the images to memory. Default: False.\n        n_thread (int): For multiprocessing.\n        map_size (int | None): Map size for lmdb env. If None, use the\n            estimated size from images. Default: None\n    \"\"\"\n\n    assert len(img_path_list) == len(keys), ('img_path_list and keys should have the same length, '\n                                             f'but got {len(img_path_list)} and {len(keys)}')\n    print(f'Create lmdb for {data_path}, save to {lmdb_path}...')\n    print(f'Totoal images: {len(img_path_list)}')\n    if not lmdb_path.endswith('.lmdb'):\n        raise ValueError(\"lmdb_path must end with '.lmdb'.\")\n    if osp.exists(lmdb_path):\n        print(f'Folder {lmdb_path} already exists. Exit.')\n        sys.exit(1)\n\n    if multiprocessing_read:\n        # read all the images to memory (multiprocessing)\n        dataset = {}  # use dict to keep the order for multiprocessing\n        shapes = {}\n        print(f'Read images with multiprocessing, #thread: {n_thread} ...')\n        pbar = tqdm(total=len(img_path_list), unit='image')\n\n        def callback(arg):\n            \"\"\"get the image data and update pbar.\"\"\"\n            key, dataset[key], shapes[key] = arg\n            pbar.update(1)\n            pbar.set_description(f'Read {key}')\n\n        pool = Pool(n_thread)\n        for path, key in zip(img_path_list, keys):\n            pool.apply_async(read_img_worker, args=(osp.join(data_path, path), key, compress_level), callback=callback)\n        pool.close()\n        pool.join()\n        pbar.close()\n        print(f'Finish reading {len(img_path_list)} images.')\n\n    # create lmdb environment\n    if map_size is None:\n        # obtain data size for one image\n        img = cv2.imread(osp.join(data_path, img_path_list[0]), cv2.IMREAD_UNCHANGED)\n        _, img_byte = cv2.imencode('.png', img, [cv2.IMWRITE_PNG_COMPRESSION, compress_level])\n        data_size_per_img = img_byte.nbytes\n        print('Data size per image is: ', data_size_per_img)\n        data_size = data_size_per_img * len(img_path_list)\n        map_size = data_size * 10\n\n    env = lmdb.open(lmdb_path, map_size=map_size)\n\n    # write data to lmdb\n    pbar = tqdm(total=len(img_path_list), unit='chunk')\n    txn = env.begin(write=True)\n    txt_file = open(osp.join(lmdb_path, 'meta_info.txt'), 'w')\n    for idx, (path, key) in enumerate(zip(img_path_list, keys)):\n        pbar.update(1)\n        pbar.set_description(f'Write {key}')\n        key_byte = key.encode('ascii')\n        if multiprocessing_read:\n            img_byte = dataset[key]\n            h, w, c = shapes[key]\n        else:\n            _, img_byte, img_shape = read_img_worker(osp.join(data_path, path), key, compress_level)\n            h, w, c = img_shape\n\n        txn.put(key_byte, img_byte)\n        # write meta information\n        txt_file.write(f'{key}.png ({h},{w},{c}) {compress_level}\\n')\n        if idx % batch == 0:\n            txn.commit()\n            txn = env.begin(write=True)\n    pbar.close()\n    txn.commit()\n    env.close()\n    txt_file.close()\n    print('\\nFinish writing lmdb.')\n\n\ndef read_img_worker(path, key, compress_level):\n    \"\"\"Read image worker.\n\n    Args:\n        path (str): Image path.\n        key (str): Image key.\n        compress_level (int): Compress level when encoding images.\n\n    Returns:\n        str: Image key.\n        byte: Image byte.\n        tuple[int]: Image shape.\n    \"\"\"\n\n    img = cv2.imread(path, cv2.IMREAD_UNCHANGED)\n    if img.ndim == 2:\n        h, w = img.shape\n        c = 1\n    else:\n        h, w, c = img.shape\n    _, img_byte = cv2.imencode('.png', img, [cv2.IMWRITE_PNG_COMPRESSION, compress_level])\n    return (key, img_byte, (h, w, c))\n\n\nclass LmdbMaker():\n    \"\"\"LMDB Maker.\n\n    Args:\n        lmdb_path (str): Lmdb save path.\n        map_size (int): Map size for lmdb env. Default: 1024 ** 4, 1TB.\n        batch (int): After processing batch images, lmdb commits.\n            Default: 5000.\n        compress_level (int): Compress level when encoding images. Default: 1.\n    \"\"\"\n\n    def __init__(self, lmdb_path, map_size=1024**4, batch=5000, compress_level=1):\n        if not lmdb_path.endswith('.lmdb'):\n            raise ValueError(\"lmdb_path must end with '.lmdb'.\")\n        if osp.exists(lmdb_path):\n            print(f'Folder {lmdb_path} already exists. Exit.')\n            sys.exit(1)\n\n        self.lmdb_path = lmdb_path\n        self.batch = batch\n        self.compress_level = compress_level\n        self.env = lmdb.open(lmdb_path, map_size=map_size)\n        self.txn = self.env.begin(write=True)\n        self.txt_file = open(osp.join(lmdb_path, 'meta_info.txt'), 'w')\n        self.counter = 0\n\n    def put(self, img_byte, key, img_shape):\n        self.counter += 1\n        key_byte = key.encode('ascii')\n        self.txn.put(key_byte, img_byte)\n        # write meta information\n        h, w, c = img_shape\n        self.txt_file.write(f'{key}.png ({h},{w},{c}) {self.compress_level}\\n')\n        if self.counter % self.batch == 0:\n            self.txn.commit()\n            self.txn = self.env.begin(write=True)\n\n    def close(self):\n        self.txn.commit()\n        self.env.close()\n        self.txt_file.close()\n"
  },
  {
    "path": "bsr/utils/logger.py",
    "content": "import datetime\nimport logging\nimport time\n\nfrom .dist_util import get_dist_info, master_only\n\ninitialized_logger = {}\n\n\nclass AvgTimer():\n\n    def __init__(self, window=200):\n        self.window = window  # average window\n        self.current_time = 0\n        self.total_time = 0\n        self.count = 0\n        self.avg_time = 0\n        self.start()\n\n    def start(self):\n        self.start_time = self.tic = time.time()\n\n    def record(self):\n        self.count += 1\n        self.toc = time.time()\n        self.current_time = self.toc - self.tic\n        self.total_time += self.current_time\n        # calculate average time\n        self.avg_time = self.total_time / self.count\n\n        # reset\n        if self.count > self.window:\n            self.count = 0\n            self.total_time = 0\n\n        self.tic = time.time()\n\n    def get_current_time(self):\n        return self.current_time\n\n    def get_avg_time(self):\n        return self.avg_time\n\n\nclass MessageLogger():\n    \"\"\"Message logger for printing.\n\n    Args:\n        opt (dict): Config. It contains the following keys:\n            name (str): Exp name.\n            logger (dict): Contains 'print_freq' (str) for logger interval.\n            train (dict): Contains 'total_iter' (int) for total iters.\n            use_tb_logger (bool): Use tensorboard logger.\n        start_iter (int): Start iter. Default: 1.\n        tb_logger (obj:`tb_logger`): Tensorboard logger. Default： None.\n    \"\"\"\n\n    def __init__(self, opt, start_iter=1, tb_logger=None):\n        self.exp_name = opt['name']\n        self.interval = opt['logger']['print_freq']\n        self.start_iter = start_iter\n        self.max_iters = opt['train']['total_iter']\n        self.use_tb_logger = opt['logger']['use_tb_logger']\n        self.tb_logger = tb_logger\n        self.start_time = time.time()\n        self.logger = get_root_logger()\n\n    def reset_start_time(self):\n        self.start_time = time.time()\n\n    @master_only\n    def __call__(self, log_vars):\n        \"\"\"Format logging message.\n\n        Args:\n            log_vars (dict): It contains the following keys:\n                epoch (int): Epoch number.\n                iter (int): Current iter.\n                lrs (list): List for learning rates.\n\n                time (float): Iter time.\n                data_time (float): Data time for each iter.\n        \"\"\"\n        # epoch, iter, learning rates\n        epoch = log_vars.pop('epoch')\n        current_iter = log_vars.pop('iter')\n        lrs = log_vars.pop('lrs')\n\n        message = (f'[{self.exp_name[:5]}..][epoch:{epoch:3d}, iter:{current_iter:8,d}, lr:(')\n        for v in lrs:\n            message += f'{v:.3e},'\n        message += ')] '\n\n        # time and estimated time\n        if 'time' in log_vars.keys():\n            iter_time = log_vars.pop('time')\n            data_time = log_vars.pop('data_time')\n\n            total_time = time.time() - self.start_time\n            time_sec_avg = total_time / (current_iter - self.start_iter + 1)\n            eta_sec = time_sec_avg * (self.max_iters - current_iter - 1)\n            eta_str = str(datetime.timedelta(seconds=int(eta_sec)))\n            message += f'[eta: {eta_str}, '\n            message += f'time (data): {iter_time:.3f} ({data_time:.3f})] '\n\n        # other items, especially losses\n        for k, v in log_vars.items():\n            message += f'{k}: {v:.4e} '\n            # tensorboard logger\n            if self.use_tb_logger and 'debug' not in self.exp_name:\n                if k.startswith('l_'):\n                    self.tb_logger.add_scalar(f'losses/{k}', v, current_iter)\n                else:\n                    self.tb_logger.add_scalar(k, v, current_iter)\n        self.logger.info(message)\n\n\n@master_only\ndef init_tb_logger(log_dir):\n    from torch.utils.tensorboard import SummaryWriter\n    tb_logger = SummaryWriter(log_dir=log_dir)\n    return tb_logger\n\n\n@master_only\ndef init_wandb_logger(opt):\n    \"\"\"We now only use wandb to sync tensorboard log.\"\"\"\n    import wandb\n    logger = get_root_logger()\n\n    project = opt['logger']['wandb']['project']\n    resume_id = opt['logger']['wandb'].get('resume_id')\n    if resume_id:\n        wandb_id = resume_id\n        resume = 'allow'\n        logger.warning(f'Resume wandb logger with id={wandb_id}.')\n    else:\n        wandb_id = wandb.util.generate_id()\n        resume = 'never'\n\n    wandb.init(id=wandb_id, resume=resume, name=opt['name'], config=opt, project=project, sync_tensorboard=True)\n\n    logger.info(f'Use wandb logger with id={wandb_id}; project={project}.')\n\n\ndef get_root_logger(logger_name='basicsr', log_level=logging.INFO, log_file=None):\n    \"\"\"Get the root logger.\n\n    The logger will be initialized if it has not been initialized. By default a\n    StreamHandler will be added. If `log_file` is specified, a FileHandler will\n    also be added.\n\n    Args:\n        logger_name (str): root logger name. Default: 'basicsr'.\n        log_file (str | None): The log filename. If specified, a FileHandler\n            will be added to the root logger.\n        log_level (int): The root logger level. Note that only the process of\n            rank 0 is affected, while other processes will set the level to\n            \"Error\" and be silent most of the time.\n\n    Returns:\n        logging.Logger: The root logger.\n    \"\"\"\n    logger = logging.getLogger(logger_name)\n    # if the logger has been initialized, just return it\n    if logger_name in initialized_logger:\n        return logger\n\n    format_str = '%(asctime)s %(levelname)s: %(message)s'\n    stream_handler = logging.StreamHandler()\n    stream_handler.setFormatter(logging.Formatter(format_str))\n    logger.addHandler(stream_handler)\n    logger.propagate = False\n    rank, _ = get_dist_info()\n    if rank != 0:\n        logger.setLevel('ERROR')\n    elif log_file is not None:\n        logger.setLevel(log_level)\n        # add file handler\n        file_handler = logging.FileHandler(log_file, 'w')\n        file_handler.setFormatter(logging.Formatter(format_str))\n        file_handler.setLevel(log_level)\n        logger.addHandler(file_handler)\n    initialized_logger[logger_name] = True\n    return logger\n\n\ndef get_env_info():\n    \"\"\"Get environment information.\n\n    Currently, only log the software version.\n    \"\"\"\n    import torch\n    import torchvision\n\n    from basicsr.version import __version__\n    msg = r\"\"\"\n                ____                _       _____  ____\n               / __ ) ____ _ _____ (_)_____/ ___/ / __ \\\n              / __  |/ __ `// ___// // ___/\\__ \\ / /_/ /\n             / /_/ // /_/ /(__  )/ // /__ ___/ // _, _/\n            /_____/ \\__,_//____//_/ \\___//____//_/ |_|\n     ______                   __   __                 __      __\n    / ____/____   ____   ____/ /  / /   __  __ _____ / /__   / /\n   / / __ / __ \\ / __ \\ / __  /  / /   / / / // ___// //_/  / /\n  / /_/ // /_/ // /_/ // /_/ /  / /___/ /_/ // /__ / /<    /_/\n  \\____/ \\____/ \\____/ \\____/  /_____/\\____/ \\___//_/|_|  (_)\n    \"\"\"\n    msg += ('\\nVersion Information: '\n            f'\\n\\tBasicSR: {__version__}'\n            f'\\n\\tPyTorch: {torch.__version__}'\n            f'\\n\\tTorchVision: {torchvision.__version__}')\n    return msg\n"
  },
  {
    "path": "bsr/utils/matlab_functions.py",
    "content": "import math\nimport numpy as np\nimport torch\n\n\ndef cubic(x):\n    \"\"\"cubic function used for calculate_weights_indices.\"\"\"\n    absx = torch.abs(x)\n    absx2 = absx**2\n    absx3 = absx**3\n    return (1.5 * absx3 - 2.5 * absx2 + 1) * (\n        (absx <= 1).type_as(absx)) + (-0.5 * absx3 + 2.5 * absx2 - 4 * absx + 2) * (((absx > 1) *\n                                                                                     (absx <= 2)).type_as(absx))\n\n\ndef calculate_weights_indices(in_length, out_length, scale, kernel, kernel_width, antialiasing):\n    \"\"\"Calculate weights and indices, used for imresize function.\n\n    Args:\n        in_length (int): Input length.\n        out_length (int): Output length.\n        scale (float): Scale factor.\n        kernel_width (int): Kernel width.\n        antialisaing (bool): Whether to apply anti-aliasing when downsampling.\n    \"\"\"\n\n    if (scale < 1) and antialiasing:\n        # Use a modified kernel (larger kernel width) to simultaneously\n        # interpolate and antialias\n        kernel_width = kernel_width / scale\n\n    # Output-space coordinates\n    x = torch.linspace(1, out_length, out_length)\n\n    # Input-space coordinates. Calculate the inverse mapping such that 0.5\n    # in output space maps to 0.5 in input space, and 0.5 + scale in output\n    # space maps to 1.5 in input space.\n    u = x / scale + 0.5 * (1 - 1 / scale)\n\n    # What is the left-most pixel that can be involved in the computation?\n    left = torch.floor(u - kernel_width / 2)\n\n    # What is the maximum number of pixels that can be involved in the\n    # computation?  Note: it's OK to use an extra pixel here; if the\n    # corresponding weights are all zero, it will be eliminated at the end\n    # of this function.\n    p = math.ceil(kernel_width) + 2\n\n    # The indices of the input pixels involved in computing the k-th output\n    # pixel are in row k of the indices matrix.\n    indices = left.view(out_length, 1).expand(out_length, p) + torch.linspace(0, p - 1, p).view(1, p).expand(\n        out_length, p)\n\n    # The weights used to compute the k-th output pixel are in row k of the\n    # weights matrix.\n    distance_to_center = u.view(out_length, 1).expand(out_length, p) - indices\n\n    # apply cubic kernel\n    if (scale < 1) and antialiasing:\n        weights = scale * cubic(distance_to_center * scale)\n    else:\n        weights = cubic(distance_to_center)\n\n    # Normalize the weights matrix so that each row sums to 1.\n    weights_sum = torch.sum(weights, 1).view(out_length, 1)\n    weights = weights / weights_sum.expand(out_length, p)\n\n    # If a column in weights is all zero, get rid of it. only consider the\n    # first and last column.\n    weights_zero_tmp = torch.sum((weights == 0), 0)\n    if not math.isclose(weights_zero_tmp[0], 0, rel_tol=1e-6):\n        indices = indices.narrow(1, 1, p - 2)\n        weights = weights.narrow(1, 1, p - 2)\n    if not math.isclose(weights_zero_tmp[-1], 0, rel_tol=1e-6):\n        indices = indices.narrow(1, 0, p - 2)\n        weights = weights.narrow(1, 0, p - 2)\n    weights = weights.contiguous()\n    indices = indices.contiguous()\n    sym_len_s = -indices.min() + 1\n    sym_len_e = indices.max() - in_length\n    indices = indices + sym_len_s - 1\n    return weights, indices, int(sym_len_s), int(sym_len_e)\n\n\n@torch.no_grad()\ndef imresize(img, scale, antialiasing=True):\n    \"\"\"imresize function same as MATLAB.\n\n    It now only supports bicubic.\n    The same scale applies for both height and width.\n\n    Args:\n        img (Tensor | Numpy array):\n            Tensor: Input image with shape (c, h, w), [0, 1] range.\n            Numpy: Input image with shape (h, w, c), [0, 1] range.\n        scale (float): Scale factor. The same scale applies for both height\n            and width.\n        antialisaing (bool): Whether to apply anti-aliasing when downsampling.\n            Default: True.\n\n    Returns:\n        Tensor: Output image with shape (c, h, w), [0, 1] range, w/o round.\n    \"\"\"\n    squeeze_flag = False\n    if type(img).__module__ == np.__name__:  # numpy type\n        numpy_type = True\n        if img.ndim == 2:\n            img = img[:, :, None]\n            squeeze_flag = True\n        img = torch.from_numpy(img.transpose(2, 0, 1)).float()\n    else:\n        numpy_type = False\n        if img.ndim == 2:\n            img = img.unsqueeze(0)\n            squeeze_flag = True\n\n    in_c, in_h, in_w = img.size()\n    out_h, out_w = math.ceil(in_h * scale), math.ceil(in_w * scale)\n    kernel_width = 4\n    kernel = 'cubic'\n\n    # get weights and indices\n    weights_h, indices_h, sym_len_hs, sym_len_he = calculate_weights_indices(in_h, out_h, scale, kernel, kernel_width,\n                                                                             antialiasing)\n    weights_w, indices_w, sym_len_ws, sym_len_we = calculate_weights_indices(in_w, out_w, scale, kernel, kernel_width,\n                                                                             antialiasing)\n    # process H dimension\n    # symmetric copying\n    img_aug = torch.FloatTensor(in_c, in_h + sym_len_hs + sym_len_he, in_w)\n    img_aug.narrow(1, sym_len_hs, in_h).copy_(img)\n\n    sym_patch = img[:, :sym_len_hs, :]\n    inv_idx = torch.arange(sym_patch.size(1) - 1, -1, -1).long()\n    sym_patch_inv = sym_patch.index_select(1, inv_idx)\n    img_aug.narrow(1, 0, sym_len_hs).copy_(sym_patch_inv)\n\n    sym_patch = img[:, -sym_len_he:, :]\n    inv_idx = torch.arange(sym_patch.size(1) - 1, -1, -1).long()\n    sym_patch_inv = sym_patch.index_select(1, inv_idx)\n    img_aug.narrow(1, sym_len_hs + in_h, sym_len_he).copy_(sym_patch_inv)\n\n    out_1 = torch.FloatTensor(in_c, out_h, in_w)\n    kernel_width = weights_h.size(1)\n    for i in range(out_h):\n        idx = int(indices_h[i][0])\n        for j in range(in_c):\n            out_1[j, i, :] = img_aug[j, idx:idx + kernel_width, :].transpose(0, 1).mv(weights_h[i])\n\n    # process W dimension\n    # symmetric copying\n    out_1_aug = torch.FloatTensor(in_c, out_h, in_w + sym_len_ws + sym_len_we)\n    out_1_aug.narrow(2, sym_len_ws, in_w).copy_(out_1)\n\n    sym_patch = out_1[:, :, :sym_len_ws]\n    inv_idx = torch.arange(sym_patch.size(2) - 1, -1, -1).long()\n    sym_patch_inv = sym_patch.index_select(2, inv_idx)\n    out_1_aug.narrow(2, 0, sym_len_ws).copy_(sym_patch_inv)\n\n    sym_patch = out_1[:, :, -sym_len_we:]\n    inv_idx = torch.arange(sym_patch.size(2) - 1, -1, -1).long()\n    sym_patch_inv = sym_patch.index_select(2, inv_idx)\n    out_1_aug.narrow(2, sym_len_ws + in_w, sym_len_we).copy_(sym_patch_inv)\n\n    out_2 = torch.FloatTensor(in_c, out_h, out_w)\n    kernel_width = weights_w.size(1)\n    for i in range(out_w):\n        idx = int(indices_w[i][0])\n        for j in range(in_c):\n            out_2[j, :, i] = out_1_aug[j, :, idx:idx + kernel_width].mv(weights_w[i])\n\n    if squeeze_flag:\n        out_2 = out_2.squeeze(0)\n    if numpy_type:\n        out_2 = out_2.numpy()\n        if not squeeze_flag:\n            out_2 = out_2.transpose(1, 2, 0)\n\n    return out_2\n"
  },
  {
    "path": "bsr/utils/misc.py",
    "content": "import numpy as np\nimport os\nimport random\nimport time\nimport torch\nfrom os import path as osp\n\nfrom .dist_util import master_only\n\n\ndef set_random_seed(seed):\n    \"\"\"Set random seeds.\"\"\"\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n\n\ndef get_time_str():\n    return time.strftime('%Y%m%d_%H%M%S', time.localtime())\n\n\ndef mkdir_and_rename(path):\n    \"\"\"mkdirs. If path exists, rename it with timestamp and create a new one.\n\n    Args:\n        path (str): Folder path.\n    \"\"\"\n    if osp.exists(path):\n        new_name = path + '_archived_' + get_time_str()\n        print(f'Path already exists. Rename it to {new_name}', flush=True)\n        os.rename(path, new_name)\n    os.makedirs(path, exist_ok=True)\n\n\n@master_only\ndef make_exp_dirs(opt):\n    \"\"\"Make dirs for experiments.\"\"\"\n    path_opt = opt['path'].copy()\n    if opt['is_train']:\n        mkdir_and_rename(path_opt.pop('experiments_root'))\n    else:\n        mkdir_and_rename(path_opt.pop('results_root'))\n    for key, path in path_opt.items():\n        if ('strict_load' in key) or ('pretrain_network' in key) or ('resume' in key) or ('param_key' in key):\n            continue\n        else:\n            os.makedirs(path, exist_ok=True)\n\n\ndef scandir(dir_path, suffix=None, recursive=False, full_path=False):\n    \"\"\"Scan a directory to find the interested files.\n\n    Args:\n        dir_path (str): Path of the directory.\n        suffix (str | tuple(str), optional): File suffix that we are\n            interested in. Default: None.\n        recursive (bool, optional): If set to True, recursively scan the\n            directory. Default: False.\n        full_path (bool, optional): If set to True, include the dir_path.\n            Default: False.\n\n    Returns:\n        A generator for all the interested files with relative paths.\n    \"\"\"\n\n    if (suffix is not None) and not isinstance(suffix, (str, tuple)):\n        raise TypeError('\"suffix\" must be a string or tuple of strings')\n\n    root = dir_path\n\n    def _scandir(dir_path, suffix, recursive):\n        for entry in os.scandir(dir_path):\n            if not entry.name.startswith('.') and entry.is_file():\n                if full_path:\n                    return_path = entry.path\n                else:\n                    return_path = osp.relpath(entry.path, root)\n\n                if suffix is None:\n                    yield return_path\n                elif return_path.endswith(suffix):\n                    yield return_path\n            else:\n                if recursive:\n                    yield from _scandir(entry.path, suffix=suffix, recursive=recursive)\n                else:\n                    continue\n\n    return _scandir(dir_path, suffix=suffix, recursive=recursive)\n\n\ndef check_resume(opt, resume_iter):\n    \"\"\"Check resume states and pretrain_network paths.\n\n    Args:\n        opt (dict): Options.\n        resume_iter (int): Resume iteration.\n    \"\"\"\n    if opt['path']['resume_state']:\n        # get all the networks\n        networks = [key for key in opt.keys() if key.startswith('network_')]\n        flag_pretrain = False\n        for network in networks:\n            if opt['path'].get(f'pretrain_{network}') is not None:\n                flag_pretrain = True\n        if flag_pretrain:\n            print('pretrain_network path will be ignored during resuming.')\n        # set pretrained model paths\n        for network in networks:\n            name = f'pretrain_{network}'\n            basename = network.replace('network_', '')\n            if opt['path'].get('ignore_resume_networks') is None or (network\n                                                                     not in opt['path']['ignore_resume_networks']):\n                opt['path'][name] = osp.join(opt['path']['models'], f'net_{basename}_{resume_iter}.pth')\n                print(f\"Set {name} to {opt['path'][name]}\")\n\n        # change param_key to params in resume\n        param_keys = [key for key in opt['path'].keys() if key.startswith('param_key')]\n        for param_key in param_keys:\n            if opt['path'][param_key] == 'params_ema':\n                opt['path'][param_key] = 'params'\n                print(f'Set {param_key} to params')\n\n\ndef sizeof_fmt(size, suffix='B'):\n    \"\"\"Get human readable file size.\n\n    Args:\n        size (int): File size.\n        suffix (str): Suffix. Default: 'B'.\n\n    Return:\n        str: Formatted file size.\n    \"\"\"\n    for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:\n        if abs(size) < 1024.0:\n            return f'{size:3.1f} {unit}{suffix}'\n        size /= 1024.0\n    return f'{size:3.1f} Y{suffix}'\n"
  },
  {
    "path": "bsr/utils/options.py",
    "content": "import argparse\nimport os\nimport random\nimport torch\nimport yaml\nfrom collections import OrderedDict\nfrom os import path as osp\n\nfrom bsr.utils import set_random_seed\nfrom bsr.utils.dist_util import get_dist_info, init_dist, master_only\n\n\ndef ordered_yaml():\n    \"\"\"Support OrderedDict for yaml.\n\n    Returns:\n        tuple: yaml Loader and Dumper.\n    \"\"\"\n    try:\n        from yaml import CDumper as Dumper\n        from yaml import CLoader as Loader\n    except ImportError:\n        from yaml import Dumper, Loader\n\n    _mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG\n\n    def dict_representer(dumper, data):\n        return dumper.represent_dict(data.items())\n\n    def dict_constructor(loader, node):\n        return OrderedDict(loader.construct_pairs(node))\n\n    Dumper.add_representer(OrderedDict, dict_representer)\n    Loader.add_constructor(_mapping_tag, dict_constructor)\n    return Loader, Dumper\n\n\ndef yaml_load(f):\n    \"\"\"Load yaml file or string.\n\n    Args:\n        f (str): File path or a python string.\n\n    Returns:\n        dict: Loaded dict.\n    \"\"\"\n    if os.path.isfile(f):\n        with open(f, 'r') as f:\n            return yaml.load(f, Loader=ordered_yaml()[0])\n    else:\n        return yaml.load(f, Loader=ordered_yaml()[0])\n\n\ndef dict2str(opt, indent_level=1):\n    \"\"\"dict to string for printing options.\n\n    Args:\n        opt (dict): Option dict.\n        indent_level (int): Indent level. Default: 1.\n\n    Return:\n        (str): Option string for printing.\n    \"\"\"\n    msg = '\\n'\n    for k, v in opt.items():\n        if isinstance(v, dict):\n            msg += ' ' * (indent_level * 2) + k + ':['\n            msg += dict2str(v, indent_level + 1)\n            msg += ' ' * (indent_level * 2) + ']\\n'\n        else:\n            msg += ' ' * (indent_level * 2) + k + ': ' + str(v) + '\\n'\n    return msg\n\n\ndef _postprocess_yml_value(value):\n    # None\n    if value == '~' or value.lower() == 'none':\n        return None\n    # bool\n    if value.lower() == 'true':\n        return True\n    elif value.lower() == 'false':\n        return False\n    # !!float number\n    if value.startswith('!!float'):\n        return float(value.replace('!!float', ''))\n    # number\n    if value.isdigit():\n        return int(value)\n    elif value.replace('.', '', 1).isdigit() and value.count('.') < 2:\n        return float(value)\n    # list\n    if value.startswith('['):\n        return eval(value)\n    # str\n    return value\n\n\ndef parse_options(root_path, is_train=True):\n    parser = argparse.ArgumentParser()\n    parser.add_argument('-opt', type=str, required=True, help='Path to option YAML file.')\n    parser.add_argument('--launcher', choices=['none', 'pytorch', 'slurm'], default='none', help='job launcher')\n    parser.add_argument('--auto_resume', action='store_true')\n    parser.add_argument('--debug', action='store_true')\n    parser.add_argument('--local_rank', type=int, default=0)\n    parser.add_argument(\n        '--force_yml', nargs='+', default=None, help='Force to update yml files. Examples: train:ema_decay=0.999')\n    args = parser.parse_args()\n\n    # parse yml to dict\n    opt = yaml_load(args.opt)\n\n    # distributed settings\n    if args.launcher == 'none':\n        opt['dist'] = False\n        print('Disable distributed.', flush=True)\n    else:\n        opt['dist'] = True\n        if args.launcher == 'slurm' and 'dist_params' in opt:\n            init_dist(args.launcher, **opt['dist_params'])\n        else:\n            init_dist(args.launcher)\n    opt['rank'], opt['world_size'] = get_dist_info()\n\n    # random seed\n    seed = opt.get('manual_seed')\n    if seed is None:\n        seed = random.randint(1, 10000)\n        opt['manual_seed'] = seed\n    set_random_seed(seed + opt['rank'])\n\n    # force to update yml options\n    if args.force_yml is not None:\n        for entry in args.force_yml:\n            # now do not support creating new keys\n            keys, value = entry.split('=')\n            keys, value = keys.strip(), value.strip()\n            value = _postprocess_yml_value(value)\n            eval_str = 'opt'\n            for key in keys.split(':'):\n                eval_str += f'[\"{key}\"]'\n            eval_str += '=value'\n            # using exec function\n            exec(eval_str)\n\n    opt['auto_resume'] = args.auto_resume\n    opt['is_train'] = is_train\n\n    # debug setting\n    if args.debug and not opt['name'].startswith('debug'):\n        opt['name'] = 'debug_' + opt['name']\n\n    if opt['num_gpu'] == 'auto':\n        opt['num_gpu'] = torch.cuda.device_count()\n\n    # datasets\n    for phase, dataset in opt['datasets'].items():\n        # for multiple datasets, e.g., val_1, val_2; test_1, test_2\n        phase = phase.split('_')[0]\n        dataset['phase'] = phase\n        if 'scale' in opt:\n            dataset['scale'] = opt['scale']\n        if dataset.get('dataroot_gt') is not None:\n            dataset['dataroot_gt'] = osp.expanduser(dataset['dataroot_gt'])\n        if dataset.get('dataroot_lq') is not None:\n            dataset['dataroot_lq'] = osp.expanduser(dataset['dataroot_lq'])\n\n    # paths\n    for key, val in opt['path'].items():\n        if (val is not None) and ('resume_state' in key or 'pretrain_network' in key):\n            opt['path'][key] = osp.expanduser(val)\n\n    if is_train:\n        experiments_root = opt['path'].get('experiments_root')\n        if experiments_root is None:\n            experiments_root = osp.join(root_path, 'experiments')\n        experiments_root = osp.join(experiments_root, opt['name'])\n\n        opt['path']['experiments_root'] = experiments_root\n        opt['path']['models'] = osp.join(experiments_root, 'models')\n        opt['path']['training_states'] = osp.join(experiments_root, 'training_states')\n        opt['path']['log'] = experiments_root\n        opt['path']['visualization'] = osp.join(experiments_root, 'visualization')\n\n        # change some options for debug mode\n        if 'debug' in opt['name']:\n            if 'val' in opt:\n                opt['val']['val_freq'] = 8\n            opt['logger']['print_freq'] = 1\n            opt['logger']['save_checkpoint_freq'] = 8\n    else:  # test\n        results_root = opt['path'].get('results_root')\n        if results_root is None:\n            results_root = osp.join(root_path, 'results')\n        results_root = osp.join(results_root, opt['name'])\n\n        opt['path']['results_root'] = results_root\n        opt['path']['log'] = results_root\n        opt['path']['visualization'] = osp.join(results_root, 'visualization')\n\n    return opt, args\n\n\n@master_only\ndef copy_opt_file(opt_file, experiments_root):\n    # copy the yml file to the experiment root\n    import sys\n    import time\n    from shutil import copyfile\n    cmd = ' '.join(sys.argv)\n    filename = osp.join(experiments_root, osp.basename(opt_file))\n    copyfile(opt_file, filename)\n\n    with open(filename, 'r+') as f:\n        lines = f.readlines()\n        lines.insert(0, f'# GENERATE TIME: {time.asctime()}\\n# CMD:\\n# {cmd}\\n\\n')\n        f.seek(0)\n        f.writelines(lines)\n"
  },
  {
    "path": "bsr/utils/plot_util.py",
    "content": "import re\n\n\ndef read_data_from_tensorboard(log_path, tag):\n    \"\"\"Get raw data (steps and values) from tensorboard events.\n\n    Args:\n        log_path (str): Path to the tensorboard log.\n        tag (str): tag to be read.\n    \"\"\"\n    from tensorboard.backend.event_processing.event_accumulator import EventAccumulator\n\n    # tensorboard event\n    event_acc = EventAccumulator(log_path)\n    event_acc.Reload()\n    scalar_list = event_acc.Tags()['scalars']\n    print('tag list: ', scalar_list)\n    steps = [int(s.step) for s in event_acc.Scalars(tag)]\n    values = [s.value for s in event_acc.Scalars(tag)]\n    return steps, values\n\n\ndef read_data_from_txt_2v(path, pattern, step_one=False):\n    \"\"\"Read data from txt with 2 returned values (usually [step, value]).\n\n    Args:\n        path (str): path to the txt file.\n        pattern (str): re (regular expression) pattern.\n        step_one (bool): add 1 to steps. Default: False.\n    \"\"\"\n    with open(path) as f:\n        lines = f.readlines()\n    lines = [line.strip() for line in lines]\n    steps = []\n    values = []\n\n    pattern = re.compile(pattern)\n    for line in lines:\n        match = pattern.match(line)\n        if match:\n            steps.append(int(match.group(1)))\n            values.append(float(match.group(2)))\n    if step_one:\n        steps = [v + 1 for v in steps]\n    return steps, values\n\n\ndef read_data_from_txt_1v(path, pattern):\n    \"\"\"Read data from txt with 1 returned values.\n\n    Args:\n        path (str): path to the txt file.\n        pattern (str): re (regular expression) pattern.\n    \"\"\"\n    with open(path) as f:\n        lines = f.readlines()\n    lines = [line.strip() for line in lines]\n    data = []\n\n    pattern = re.compile(pattern)\n    for line in lines:\n        match = pattern.match(line)\n        if match:\n            data.append(float(match.group(1)))\n    return data\n\n\ndef smooth_data(values, smooth_weight):\n    \"\"\" Smooth data using 1st-order IIR low-pass filter (what tensorflow does).\n\n    Reference: https://github.com/tensorflow/tensorboard/blob/f801ebf1f9fbfe2baee1ddd65714d0bccc640fb1/tensorboard/plugins/scalar/vz_line_chart/vz-line-chart.ts#L704  # noqa: E501\n\n    Args:\n        values (list): A list of values to be smoothed.\n        smooth_weight (float): Smooth weight.\n    \"\"\"\n    values_sm = []\n    last_sm_value = values[0]\n    for value in values:\n        value_sm = last_sm_value * smooth_weight + (1 - smooth_weight) * value\n        values_sm.append(value_sm)\n        last_sm_value = value_sm\n    return values_sm\n"
  },
  {
    "path": "bsr/utils/registry.py",
    "content": "# Modified from: https://github.com/facebookresearch/fvcore/blob/master/fvcore/common/registry.py  # noqa: E501\n\n\nclass Registry():\n    \"\"\"\n    The registry that provides name -> object mapping, to support third-party\n    users' custom modules.\n\n    To create a registry (e.g. a backbone registry):\n\n    .. code-block:: python\n\n        BACKBONE_REGISTRY = Registry('BACKBONE')\n\n    To register an object:\n\n    .. code-block:: python\n\n        @BACKBONE_REGISTRY.register()\n        class MyBackbone():\n            ...\n\n    Or:\n\n    .. code-block:: python\n\n        BACKBONE_REGISTRY.register(MyBackbone)\n    \"\"\"\n\n    def __init__(self, name):\n        \"\"\"\n        Args:\n            name (str): the name of this registry\n        \"\"\"\n        self._name = name\n        self._obj_map = {}\n\n    def _do_register(self, name, obj, suffix=None):\n        if isinstance(suffix, str):\n            name = name + '_' + suffix\n\n        assert (name not in self._obj_map), (f\"An object named '{name}' was already registered \"\n                                             f\"in '{self._name}' registry!\")\n        self._obj_map[name] = obj\n\n    def register(self, obj=None, suffix=None):\n        \"\"\"\n        Register the given object under the the name `obj.__name__`.\n        Can be used as either a decorator or not.\n        See docstring of this class for usage.\n        \"\"\"\n        if obj is None:\n            # used as a decorator\n            def deco(func_or_class):\n                name = func_or_class.__name__\n                self._do_register(name, func_or_class, suffix)\n                return func_or_class\n\n            return deco\n\n        # used as a function call\n        name = obj.__name__\n        self._do_register(name, obj, suffix)\n\n    def get(self, name, suffix='basicsr'):\n        ret = self._obj_map.get(name)\n        if ret is None:\n            ret = self._obj_map.get(name + '_' + suffix)\n            print(f'Name {name} is not found, use name: {name}_{suffix}!')\n        if ret is None:\n            raise KeyError(f\"No object named '{name}' found in '{self._name}' registry!\")\n        return ret\n\n    def __contains__(self, name):\n        return name in self._obj_map\n\n    def __iter__(self):\n        return iter(self._obj_map.items())\n\n    def keys(self):\n        return self._obj_map.keys()\n\n\nDATASET_REGISTRY = Registry('dataset')\nARCH_REGISTRY = Registry('arch')\nMODEL_REGISTRY = Registry('model')\nLOSS_REGISTRY = Registry('loss')\nMETRIC_REGISTRY = Registry('metric')\n"
  },
  {
    "path": "config.yml",
    "content": "dataroot_gt: path_to_HR_images_of_LSDIR\n\nscale: 4\n\n# the first degradation process\nresize_prob: [0.2, 0.7, 0.1]  # up, down, keep\nresize_range: [0.3, 1.5]\ngaussian_noise_prob: 0.5\nnoise_range: [1, 15]\npoisson_scale_range: [0.05, 2.0]\ngray_noise_prob: 0.4\njpeg_range: [60, 95]\n\n# the second degradation process\nsecond_blur_prob: 0.5\nresize_prob2: [0.3, 0.4, 0.3]  # up, down, keep\nresize_range2: [0.6, 1.2]\ngaussian_noise_prob2: 0.5\nnoise_range2: [1, 12]\npoisson_scale_range2: [0.05, 1.0]\ngray_noise_prob2: 0.4\njpeg_range2: [60, 100]\n\ngt_size: 512\n\nblur_kernel_size: 21\nkernel_list: ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso']\nkernel_prob: [0.45, 0.25, 0.12, 0.03, 0.12, 0.03]\nsinc_prob: 0.1\nblur_sigma: [0.2, 1.5]\nbetag_range: [0.5, 2.0]\nbetap_range: [1, 1.5]\n\nblur_kernel_size2: 11\nkernel_list2: ['iso', 'aniso', 'generalized_iso', 'generalized_aniso', 'plateau_iso', 'plateau_aniso']\nkernel_prob2: [0.45, 0.25, 0.12, 0.03, 0.12, 0.03]\nsinc_prob2: 0.1\nblur_sigma2: [0.2, 1.0]\nbetag_range2: [0.5, 2.0]\nbetap_range2: [1, 1.5]\n\nfinal_sinc_prob: 0.8\n\nuse_hflip: True\nuse_rot: False\n\niter_num: 1000"
  },
  {
    "path": "dataset.py",
    "content": "import torch, random, cv2, os, math, glob\nimport torch.nn.functional as F\nimport numpy as np\nfrom bsr.degradations import circular_lowpass_kernel, random_mixed_kernels, random_add_gaussian_noise_pt, random_add_poisson_noise_pt\nfrom bsr.transforms import augment, paired_random_crop\nfrom bsr.utils import FileClient, imfrombytes, img2tensor, DiffJPEG\nfrom bsr.utils.img_process_util import filter2D\n\nclass RealESRGANDataset(torch.utils.data.Dataset):\n    def __init__(self, opt, bsz):\n        super(RealESRGANDataset, self).__init__()\n        self.opt = opt\n        self.file_client = FileClient(\"disk\")\n        self.gt_folder = opt[\"dataroot_gt\"]\n        self.len = bsz * opt[\"iter_num\"]\n        self.paths = glob.glob(os.path.join(self.gt_folder, \"**/*\"), recursive=True)\n\n        # blur settings for the first degradation\n        self.blur_kernel_size = opt[\"blur_kernel_size\"]\n        self.kernel_list = opt[\"kernel_list\"]\n        self.kernel_prob = opt[\"kernel_prob\"]  # a list for each kernel probability\n        self.blur_sigma = opt[\"blur_sigma\"]\n        self.betag_range = opt[\"betag_range\"]  # betag used in generalized Gaussian blur kernels\n        self.betap_range = opt[\"betap_range\"]  # betap used in plateau blur kernels\n        self.sinc_prob = opt[\"sinc_prob\"]  # the probability for sinc filters\n\n        # blur settings for the second degradation\n        self.blur_kernel_size2 = opt[\"blur_kernel_size2\"]\n        self.kernel_list2 = opt[\"kernel_list2\"]\n        self.kernel_prob2 = opt[\"kernel_prob2\"]\n        self.blur_sigma2 = opt[\"blur_sigma2\"]\n        self.betag_range2 = opt[\"betag_range2\"]\n        self.betap_range2 = opt[\"betap_range2\"]\n        self.sinc_prob2 = opt[\"sinc_prob2\"]\n\n        # a final sinc filter\n        self.final_sinc_prob = opt[\"final_sinc_prob\"]\n\n        self.kernel_range = [2 * v + 1 for v in range(3, 11)]  # kernel size ranges from 7 to 21\n        # TODO: kernel range is now hard-coded, should be in the configure file\n        self.pulse_tensor = torch.zeros(21, 21).float()  # convolving with pulse tensor brings no blurry effect\n        self.pulse_tensor[10, 10] = 1\n\n    def __getitem__(self, index):\n        index = random.randint(0, len(self.paths) - 1)\n        gt_path = self.paths[index]\n        img_gt = imfrombytes(self.file_client.get(gt_path, \"gt\"), float32=True)\n        img_gt = augment(img_gt, self.opt[\"use_hflip\"], self.opt[\"use_rot\"])\n        h, w = img_gt.shape[0:2]\n        crop_pad_size = self.opt.gt_size\n        if h < crop_pad_size or w < crop_pad_size:\n            pad_h = max(0, crop_pad_size - h)\n            pad_w = max(0, crop_pad_size - w)\n            img_gt = cv2.copyMakeBorder(img_gt, 0, pad_h, 0, pad_w, cv2.BORDER_REFLECT_101)\n        if img_gt.shape[0] > crop_pad_size or img_gt.shape[1] > crop_pad_size:\n            h, w = img_gt.shape[0:2]\n            top = random.randint(0, h - crop_pad_size)\n            left = random.randint(0, w - crop_pad_size)\n            img_gt = img_gt[top:top + crop_pad_size, left:left + crop_pad_size, ...]\n\n        # ------------------------ Generate kernels (used in the first degradation) ------------------------ #\n        kernel_size = random.choice(self.kernel_range)\n        if np.random.uniform() < self.opt[\"sinc_prob\"]:\n            # this sinc filter setting is for kernels ranging from [7, 21]\n            if kernel_size < 13:\n                omega_c = np.random.uniform(np.pi / 3, np.pi)\n            else:\n                omega_c = np.random.uniform(np.pi / 5, np.pi)\n            kernel = circular_lowpass_kernel(omega_c, kernel_size, pad_to=False)\n        else:\n            kernel = random_mixed_kernels(\n                self.kernel_list,\n                self.kernel_prob,\n                kernel_size,\n                self.blur_sigma,\n                self.blur_sigma, [-math.pi, math.pi],\n                self.betag_range,\n                self.betap_range,\n                noise_range=None)\n        # pad kernel\n        pad_size = (21 - kernel_size) // 2\n        kernel = np.pad(kernel, ((pad_size, pad_size), (pad_size, pad_size)))\n\n        # ------------------------ Generate kernels (used in the second degradation) ------------------------ #\n        kernel_size = random.choice(self.kernel_range)\n        if np.random.uniform() < self.opt[\"sinc_prob2\"]:\n            if kernel_size < 13:\n                omega_c = np.random.uniform(np.pi / 3, np.pi)\n            else:\n                omega_c = np.random.uniform(np.pi / 5, np.pi)\n            kernel2 = circular_lowpass_kernel(omega_c, kernel_size, pad_to=False)\n        else:\n            kernel2 = random_mixed_kernels(\n                self.kernel_list2,\n                self.kernel_prob2,\n                kernel_size,\n                self.blur_sigma2,\n                self.blur_sigma2, [-math.pi, math.pi],\n                self.betag_range2,\n                self.betap_range2,\n                noise_range=None)\n\n        # pad kernel\n        pad_size = (21 - kernel_size) // 2\n        kernel2 = np.pad(kernel2, ((pad_size, pad_size), (pad_size, pad_size)))\n\n        # ------------------------------------- the final sinc kernel ------------------------------------- #\n        if np.random.uniform() < self.opt[\"final_sinc_prob\"]:\n            kernel_size = random.choice(self.kernel_range)\n            omega_c = np.random.uniform(np.pi / 3, np.pi)\n            sinc_kernel = circular_lowpass_kernel(omega_c, kernel_size, pad_to=21)\n            sinc_kernel = torch.FloatTensor(sinc_kernel)\n        else:\n            sinc_kernel = self.pulse_tensor\n\n        # BGR to RGB, HWC to CHW, numpy to tensor\n        img_gt = img2tensor([img_gt], bgr2rgb=True, float32=True)[0]\n        kernel = torch.FloatTensor(kernel)\n        kernel2 = torch.FloatTensor(kernel2)\n\n        return_d = {\"gt\": img_gt, \"kernel1\": kernel, \"kernel2\": kernel2, \"sinc_kernel\": sinc_kernel, \"gt_path\": gt_path}\n        return return_d\n\n    def __len__(self):\n        return self.len\n\nclass RealESRGANDegrader:\n    def __init__(self, opt, device):\n        self.opt = opt\n        self.device = device\n        self.jpeger = DiffJPEG(differentiable=False).to(device)  # simulate JPEG compression artifacts\n        self.queue_size = 1200\n\n    @torch.no_grad()\n    def _dequeue_and_enqueue(self):\n        \"\"\"It is the training pair pool for increasing the diversity in a batch.\n\n        Batch processing limits the diversity of synthetic degradations in a batch. For example, samples in a\n        batch could not have different resize scaling factors. Therefore, we employ this training pair pool\n        to increase the degradation diversity in a batch.\n        \"\"\"\n        # initialize\n        b, c, h, w = self.lq.size()\n        if not hasattr(self, \"queue_lr\"):\n            assert self.queue_size % b == 0, f\"queue size {self.queue_size} should be divisible by batch size {b}\"\n            self.queue_lr = torch.zeros(self.queue_size, c, h, w).to(self.device)\n            _, c, h, w = self.gt.size()\n            self.queue_gt = torch.zeros(self.queue_size, c, h, w).to(self.device)\n            self.queue_ptr = 0\n        if self.queue_ptr == self.queue_size:  # the pool is full\n            # do dequeue and enqueue\n            # shuffle\n            idx = torch.randperm(self.queue_size)\n            self.queue_lr = self.queue_lr[idx]\n            self.queue_gt = self.queue_gt[idx]\n            # get first b samples\n            lq_dequeue = self.queue_lr[0:b, :, :, :].clone()\n            gt_dequeue = self.queue_gt[0:b, :, :, :].clone()\n            # update the queue\n            self.queue_lr[0:b, :, :, :] = self.lq.clone()\n            self.queue_gt[0:b, :, :, :] = self.gt.clone()\n\n            self.lq = lq_dequeue\n            self.gt = gt_dequeue\n        else:\n            # only do enqueue\n            self.queue_lr[self.queue_ptr:self.queue_ptr + b, :, :, :] = self.lq.clone()\n            self.queue_gt[self.queue_ptr:self.queue_ptr + b, :, :, :] = self.gt.clone()\n            self.queue_ptr = self.queue_ptr + b\n\n    @torch.no_grad()\n    def degrade(self, data):\n        \"\"\"Accept data from dataloader, and then add two-order degradations to obtain LQ images.\n        \"\"\"\n        # training data synthesis\n        self.gt = data[\"gt\"].to(self.device)\n\n        self.kernel1 = data[\"kernel1\"].to(self.device)\n        self.kernel2 = data[\"kernel2\"].to(self.device)\n        self.sinc_kernel = data[\"sinc_kernel\"].to(self.device)\n\n        ori_h, ori_w = self.gt.size()[2:4]\n\n        # ----------------------- The first degradation process ----------------------- #\n        # blur\n        out = filter2D(self.gt, self.kernel1)\n        # random resize\n        updown_type = random.choices([\"up\", \"down\", \"keep\"], self.opt[\"resize_prob\"])[0]\n        if updown_type == \"up\":\n            scale = np.random.uniform(1, self.opt[\"resize_range\"][1])\n        elif updown_type == \"down\":\n            scale = np.random.uniform(self.opt[\"resize_range\"][0], 1)\n        else:\n            scale = 1\n        mode = random.choice([\"area\", \"bilinear\", \"bicubic\"])\n        out = F.interpolate(out, scale_factor=scale, mode=mode)\n        # add noise\n        gray_noise_prob = self.opt[\"gray_noise_prob\"]\n        if np.random.uniform() < self.opt[\"gaussian_noise_prob\"]:\n            out = random_add_gaussian_noise_pt(\n                out, sigma_range=self.opt[\"noise_range\"], clip=True, rounds=False, gray_prob=gray_noise_prob)\n        else:\n            out = random_add_poisson_noise_pt(\n                out,\n                scale_range=self.opt[\"poisson_scale_range\"],\n                gray_prob=gray_noise_prob,\n                clip=True,\n                rounds=False)\n        # JPEG compression\n        jpeg_p = out.new_zeros(out.size(0)).uniform_(*self.opt[\"jpeg_range\"])\n        out = torch.clamp(out, 0, 1)  # clamp to [0, 1], otherwise JPEGer will result in unpleasant artifacts\n        out = self.jpeger(out, quality=jpeg_p)\n\n        # ----------------------- The second degradation process ----------------------- #\n        # blur\n        if np.random.uniform() < self.opt[\"second_blur_prob\"]:\n            out = filter2D(out, self.kernel2)\n        # random resize\n        updown_type = random.choices([\"up\", \"down\", \"keep\"], self.opt[\"resize_prob2\"])[0]\n        if updown_type == \"up\":\n            scale = np.random.uniform(1, self.opt[\"resize_range2\"][1])\n        elif updown_type == \"down\":\n            scale = np.random.uniform(self.opt[\"resize_range2\"][0], 1)\n        else:\n            scale = 1\n        mode = random.choice([\"area\", \"bilinear\", \"bicubic\"])\n        out = F.interpolate(\n            out, size=(int(ori_h / self.opt[\"scale\"] * scale), int(ori_w / self.opt[\"scale\"] * scale)), mode=mode)\n        # add noise\n        gray_noise_prob = self.opt[\"gray_noise_prob2\"]\n        if np.random.uniform() < self.opt[\"gaussian_noise_prob2\"]:\n            out = random_add_gaussian_noise_pt(\n                out, sigma_range=self.opt[\"noise_range2\"], clip=True, rounds=False, gray_prob=gray_noise_prob)\n        else:\n            out = random_add_poisson_noise_pt(\n                out,\n                scale_range=self.opt[\"poisson_scale_range2\"],\n                gray_prob=gray_noise_prob,\n                clip=True,\n                rounds=False)\n\n        # JPEG compression + the final sinc filter\n        # We also need to resize images to desired sizes. We group [resize back + sinc filter] together\n        # as one operation.\n        # We consider two orders:\n        #   1. [resize back + sinc filter] + JPEG compression\n        #   2. JPEG compression + [resize back + sinc filter]\n        # Empirically, we find other combinations (sinc + JPEG + Resize) will introduce twisted lines.\n        if np.random.uniform() < 0.5:\n            # resize back + the final sinc filter\n            mode = random.choice([\"area\", \"bilinear\", \"bicubic\"])\n            out = F.interpolate(out, size=(ori_h // self.opt[\"scale\"], ori_w // self.opt[\"scale\"]), mode=mode)\n            out = filter2D(out, self.sinc_kernel)\n            # JPEG compression\n            jpeg_p = out.new_zeros(out.size(0)).uniform_(*self.opt[\"jpeg_range2\"])\n            out = torch.clamp(out, 0, 1)\n            out = self.jpeger(out, quality=jpeg_p)\n        else:\n            # JPEG compression\n            jpeg_p = out.new_zeros(out.size(0)).uniform_(*self.opt[\"jpeg_range2\"])\n            out = torch.clamp(out, 0, 1)\n            out = self.jpeger(out, quality=jpeg_p)\n            # resize back + the final sinc filter\n            mode = random.choice([\"area\", \"bilinear\", \"bicubic\"])\n            out = F.interpolate(out, size=(ori_h // self.opt[\"scale\"], ori_w // self.opt[\"scale\"]), mode=mode)\n            out = filter2D(out, self.sinc_kernel)\n\n        # clamp and round\n        self.lq = torch.clamp((out * 255.0).round(), 0, 255) / 255.\n\n        # random crop\n        gt_size = self.opt[\"gt_size\"]\n        self.gt, self.lq = paired_random_crop(self.gt, self.lq, gt_size, self.opt[\"scale\"])\n\n        # training pair pool\n        self._dequeue_and_enqueue()\n        # sharpen self.gt again, as we have changed the self.gt with self._dequeue_and_enqueue\n        self.lq = self.lq.contiguous()  # for the warning: grad and param do not obey the gradient layout contract\n\n        return self.lq, self.gt\n"
  },
  {
    "path": "evaluate.py",
    "content": "import torch, os, glob, pyiqa\nfrom argparse import ArgumentParser\nimport numpy as np\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom torchvision import transforms\n\nparser = ArgumentParser()\nparser.add_argument(\"--HR_dir\", type=str, default=\"testset/RealSR/HR\")\nparser.add_argument(\"--SR_dir\", type=str, default=\"result/RealSR\")\nargs = parser.parse_args()\n\ndevice = torch.device(\"cuda\")\n\npsnr = pyiqa.create_metric(\"psnr\", test_y_channel=True, color_space=\"ycbcr\", device=device)\nssim = pyiqa.create_metric(\"ssim\", test_y_channel=True, color_space=\"ycbcr\", device=device)\nlpips = pyiqa.create_metric(\"lpips\", device=device)\ndists = pyiqa.create_metric(\"dists\", device=device)\nfid = pyiqa.create_metric(\"fid\", device=device)\nniqe = pyiqa.create_metric(\"niqe\", device=device)\nmaniqa = pyiqa.create_metric(\"maniqa-pipal\", device=device)\nclipiqa = pyiqa.create_metric(\"clipiqa\", device=device)\nmusiq = pyiqa.create_metric(\"musiq\", device=device)\n\ntest_SR_paths = list(sorted(glob.glob(os.path.join(args.SR_dir, \"*\"))))\ntest_HR_paths = list(sorted(glob.glob(os.path.join(args.HR_dir, \"*\"))))\n\nmetrics = {\"psnr\": [], \"ssim\": [], \"lpips\": [], \"dists\": [], \"niqe\": [], \"maniqa\": [], \"musiq\": [], \"clipiqa\": []}\n\nfor i, (SR_path, HR_path) in tqdm(enumerate(zip(test_SR_paths, test_HR_paths))):\n    SR = Image.open(SR_path).convert(\"RGB\")\n    SR = transforms.ToTensor()(SR).to(device).unsqueeze(0)\n    HR = Image.open(HR_path).convert(\"RGB\")\n    HR = transforms.ToTensor()(HR).to(device).unsqueeze(0)\n    metrics[\"psnr\"].append(psnr(SR, HR).item())\n    metrics[\"ssim\"].append(ssim(SR, HR).item())\n    metrics[\"lpips\"].append(lpips(SR, HR).item())\n    metrics[\"dists\"].append(dists(SR, HR).item())\n    metrics[\"niqe\"].append(niqe(SR).item())\n    metrics[\"maniqa\"].append(maniqa(SR).item())\n    metrics[\"clipiqa\"].append(clipiqa(SR).item())\n    metrics[\"musiq\"].append(musiq(SR).item())\n\nfor k in metrics.keys():\n    metrics[k] = np.mean(metrics[k])\n\nmetrics[\"fid\"] = fid(args.SR_dir, args.HR_dir)\n\nfor k, v in metrics.items():\n    if k == \"niqe\":\n        print(k, f\"{v:.3g}\")\n    elif k == \"fid\":\n        print(k, f\"{v:.5g}\")\n    else:\n        print(k, f\"{v:.4g}\")"
  },
  {
    "path": "evaluate_debug.sh",
    "content": "HF_ENDPOINT=https://hf-mirror.com \\\nCUDA_VISIBLE_DEVICES=0 \\\npython -u evaluate.py \\\n--HR_dir=testset/RealSR/HR \\\n--SR_dir=result/RealSR\n"
  },
  {
    "path": "forward.py",
    "content": "import torch\n\ndef MyUNet2DConditionModel_SD_forward(self, x):\n    global skip\n    x = self.conv_in(x)\n    skip = [x]\n    x = self.body(x)\n    return x\n\ndef MyCrossAttnDownBlock2D_SD_forward(self, x):\n    for i in range(2):\n        x = self.resnets[i](x)\n        x = self.attentions[i](x)\n        skip.append(x)\n    if self.downsamplers is not None:\n        x = self.downsamplers[0](x)\n        skip.append(x)\n    return x\n\ndef MyCrossAttnUpBlock2D_SD_forward(self, x):\n    for i in range(3):\n        x = self.resnets[i](torch.cat([x, skip.pop()], dim=1))\n        x = self.attentions[i](x)\n    if self.upsamplers is not None:\n        x = self.upsamplers[0](x)\n    return x\n\ndef MyDownBlock2D_SD_forward(self, x):\n    for i in range(2):\n        x = self.resnets[i](x)\n        skip.append(x)\n    return x\n\ndef MyUNetMidBlock2DCrossAttn_SD_forward(self, x):\n    x = self.resnets[0](x)\n    x = self.attentions[0](x)\n    x = self.resnets[1](x)\n    return x\n\ndef MyUpBlock2D_SD_forward(self, x):\n    for i in range(3):\n        x = self.resnets[i](torch.cat([x, skip.pop()], dim=1))\n    x = self.upsamplers[0](x)\n    return x\n\ndef MyResnetBlock2D_SD_forward(self, x_in):\n    x = self.norm1(x_in)\n    x = self.nonlinearity(x)\n    x = self.conv1(x)\n    x = self.norm2(x)\n    x = self.nonlinearity(x)\n    x = self.conv2(x)\n    if self.in_channels == self.out_channels:\n        return x + x_in\n    return x + self.conv_shortcut(x_in)\n\ndef MyTransformer2DModel_SD_forward(self, x_in):\n    b, c, h, w = x_in.shape\n    x = self.norm(x_in)\n    x = x.permute(0, 2, 3, 1).reshape(b, h * w, c).contiguous()\n    x = self.proj_in(x)\n    for block in self.transformer_blocks:\n        x = x + block.attn1(block.norm1(x))\n        x = x + block.ff(block.norm3(x))\n    x = self.proj_out(x)\n    x = x.reshape(b, h, w, c).permute(0, 3, 1, 2).contiguous()\n    return x + x_in"
  },
  {
    "path": "model.py",
    "content": "import torch, types, copy\r\nfrom torch import nn\r\nimport torch.nn.functional as F\r\nfrom diffusers.models.unets.unet_2d_blocks import CrossAttnDownBlock2D, \\\r\n                                                  CrossAttnUpBlock2D, \\\r\n                                                  DownBlock2D, \\\r\n                                                  UpBlock2D, \\\r\n                                                  UNetMidBlock2DCrossAttn\r\nfrom diffusers.models.resnet import ResnetBlock2D\r\nfrom diffusers.models.transformers.transformer_2d import Transformer2DModel\r\nfrom diffusers.models.attention import BasicTransformerBlock\r\nfrom diffusers.models.downsampling import Downsample2D\r\nfrom diffusers.models.upsampling import Upsample2D\r\nfrom forward import MyUNet2DConditionModel_SD_forward, \\\r\n                    MyCrossAttnDownBlock2D_SD_forward, \\\r\n                    MyDownBlock2D_SD_forward, \\\r\n                    MyUNetMidBlock2DCrossAttn_SD_forward, \\\r\n                    MyCrossAttnUpBlock2D_SD_forward, \\\r\n                    MyUpBlock2D_SD_forward, \\\r\n                    MyResnetBlock2D_SD_forward, \\\r\n                    MyTransformer2DModel_SD_forward\r\n\r\ndef find_parent(model, module_name):\r\n    components = module_name.split(\".\")\r\n    parent = model\r\n    for comp in components[:-1]:\r\n        parent = getattr(parent, comp)\r\n    return parent, components[-1]\r\n\r\ndef halve_channels(model):\r\n    for name, module in model.named_modules():\r\n        if hasattr(module, \"pruned\"):\r\n            continue\r\n        if isinstance(module, nn.Conv2d):\r\n            in_channels = int(module.in_channels * 0.75)\r\n            out_channels = int(module.out_channels * 0.75)\r\n            new_conv = nn.Conv2d(in_channels=in_channels,\r\n                                 out_channels=out_channels,\r\n                                 kernel_size=module.kernel_size,\r\n                                 stride=module.stride,\r\n                                 padding=module.padding,\r\n                                 dilation=module.dilation,\r\n                                 groups=module.groups,\r\n                                 bias=module.bias is not None)\r\n            with torch.no_grad():\r\n                new_conv.weight.copy_(module.weight[:out_channels, :in_channels])\r\n                if module.bias is not None:\r\n                    new_conv.bias.copy_(module.bias[:out_channels])\r\n            parent, last_name = find_parent(model, name)\r\n            setattr(parent, last_name, new_conv)\r\n            new_conv.pruned = True\r\n        elif isinstance(module, nn.Linear):\r\n            in_features = int(module.in_features * 0.75)\r\n            out_features = int(module.out_features * 0.75)\r\n            new_linear = nn.Linear(in_features=in_features,\r\n                                   out_features=out_features,\r\n                                   bias=module.bias is not None)\r\n            with torch.no_grad():\r\n                new_linear.weight.copy_(module.weight[:out_features, :in_features])\r\n                if module.bias is not None:\r\n                    new_linear.bias.copy_(module.bias[:out_features])\r\n            parent, last_name = find_parent(model, name)\r\n            setattr(parent, last_name, new_linear)\r\n            new_linear.pruned = True\r\n        elif isinstance(module, nn.GroupNorm):\r\n            num_channels = int(module.num_channels * 0.75)\r\n            for num_groups in [32, 24, 16, 12, 8, 6, 4, 2, 1]:\r\n                if num_channels % num_groups == 0:\r\n                    break\r\n            new_gn = nn.GroupNorm(num_groups=num_groups,\r\n                                  num_channels=num_channels,\r\n                                  eps=module.eps,\r\n                                  affine=module.affine)\r\n            with torch.no_grad():\r\n                new_gn.weight.copy_(module.weight[:num_channels])\r\n                new_gn.bias.copy_(module.bias[:num_channels])\r\n            parent, last_name = find_parent(model, name)\r\n            setattr(parent, last_name, new_gn)\r\n            new_gn.pruned = True\r\n        elif isinstance(module, nn.LayerNorm):\r\n            normalized_shape = int(module.normalized_shape[0] * 0.75)\r\n            new_ln = nn.LayerNorm(normalized_shape, \r\n                                  eps=module.eps, \r\n                                  elementwise_affine=module.elementwise_affine)\r\n            with torch.no_grad():\r\n                new_ln.weight.copy_(module.weight[:normalized_shape])\r\n                new_ln.bias.copy_(module.bias[:normalized_shape])\r\n            parent, last_name = find_parent(model, name)\r\n            setattr(parent, last_name, new_ln)\r\n            new_ln.pruned = True\r\n        elif isinstance(module, Downsample2D) or isinstance(module, Upsample2D):\r\n            module.channels = int(module.channels * 0.75)\r\n\r\nclass Net(nn.Module):\r\n    def __init__(self, unet, decoder):\r\n        super().__init__()\r\n        del unet.time_embedding\r\n        new_conv_in = nn.Conv2d(16, 320, 3, padding=1)\r\n        new_conv_in.weight.data = unet.conv_in.weight.data.repeat(1, 4, 1, 1)\r\n        new_conv_in.bias.data = unet.conv_in.bias.data\r\n        unet.conv_in = new_conv_in\r\n        new_conv_out = nn.Conv2d(320, 342, 3, padding=1)\r\n        new_conv_out.weight.data = unet.conv_out.weight.data.repeat(86, 1, 1, 1)[:342]\r\n        new_conv_out.bias.data = unet.conv_out.bias.data.repeat(86,)[:342]\r\n        unet.conv_out = new_conv_out\r\n        def ResnetBlock2D_remove_time_emb_proj(module):\r\n            if isinstance(module, ResnetBlock2D):\r\n                del module.time_emb_proj\r\n        unet.apply(ResnetBlock2D_remove_time_emb_proj)\r\n        def BasicTransformerBlock_remove_cross_attn(module):\r\n            if isinstance(module, BasicTransformerBlock):\r\n                del module.attn2, module.norm2\r\n        unet.apply(BasicTransformerBlock_remove_cross_attn)\r\n        def set_inplace_to_true(module):\r\n            if isinstance(module, nn.Dropout) or isinstance(module, nn.SiLU):\r\n                module.inplace = True\r\n        unet.apply(set_inplace_to_true)\r\n        def replace_forward_methods(module):\r\n            if isinstance(module, CrossAttnDownBlock2D):\r\n                module.forward = types.MethodType(MyCrossAttnDownBlock2D_SD_forward, module)\r\n            elif isinstance(module, DownBlock2D):\r\n                module.forward = types.MethodType(MyDownBlock2D_SD_forward, module)\r\n            elif isinstance(module, UNetMidBlock2DCrossAttn):\r\n                module.forward = types.MethodType(MyUNetMidBlock2DCrossAttn_SD_forward, module)\r\n            elif isinstance(module, UpBlock2D):\r\n                module.forward = types.MethodType(MyUpBlock2D_SD_forward, module)\r\n            elif isinstance(module, CrossAttnUpBlock2D):\r\n                module.forward = types.MethodType(MyCrossAttnUpBlock2D_SD_forward, module)\r\n            elif isinstance(module, ResnetBlock2D):\r\n                module.forward = types.MethodType(MyResnetBlock2D_SD_forward, module)\r\n            elif isinstance(module, Transformer2DModel):\r\n                module.forward = types.MethodType(MyTransformer2DModel_SD_forward, module)\r\n        unet.apply(replace_forward_methods)\r\n        unet.forward = types.MethodType(MyUNet2DConditionModel_SD_forward, unet)\r\n        halve_channels(unet)\r\n        unet.body = nn.Sequential(\r\n            *unet.down_blocks,\r\n            unet.mid_block,\r\n            *unet.up_blocks,\r\n            unet.conv_norm_out,\r\n            unet.conv_act,\r\n            unet.conv_out,\r\n        )\r\n        del decoder.conv_in, decoder.up_blocks, decoder.conv_norm_out, decoder.conv_act, decoder.conv_out\r\n        self.body = nn.Sequential(\r\n            nn.PixelUnshuffle(2),\r\n            unet,\r\n            decoder.mid_block,\r\n        )\r\n    \r\n    def forward(self, x):\r\n        return self.body(x)"
  },
  {
    "path": "ram/configs/condition_config.json",
    "content": "{\n    \"nf\": 64\n  }"
  },
  {
    "path": "ram/configs/med_config.json",
    "content": "{\n    \"architectures\": [\n      \"BertModel\"\n    ],\n    \"attention_probs_dropout_prob\": 0.1,\n    \"hidden_act\": \"gelu\",\n    \"hidden_dropout_prob\": 0.1,\n    \"hidden_size\": 768,\n    \"initializer_range\": 0.02,\n    \"intermediate_size\": 3072,\n    \"layer_norm_eps\": 1e-12,\n    \"max_position_embeddings\": 512,\n    \"model_type\": \"bert\",\n    \"num_attention_heads\": 12,\n    \"num_hidden_layers\": 12,\n    \"pad_token_id\": 0,\n    \"type_vocab_size\": 2,\n    \"vocab_size\": 30524,\n    \"encoder_width\": 768,\n    \"add_cross_attention\": true   \n  }"
  },
  {
    "path": "ram/configs/q2l_config.json",
    "content": "{\n    \"architectures\": [\n      \"BertModel\"\n    ],\n    \"attention_probs_dropout_prob\": 0.1,\n    \"hidden_act\": \"gelu\",\n    \"hidden_dropout_prob\": 0.1,\n    \"hidden_size\": 768,\n    \"initializer_range\": 0.02,\n    \"intermediate_size\": 3072,\n    \"layer_norm_eps\": 1e-12,\n    \"max_position_embeddings\": 512,\n    \"model_type\": \"bert\",\n    \"num_attention_heads\": 4,\n    \"num_hidden_layers\": 2,\n    \"pad_token_id\": 0,\n    \"type_vocab_size\": 2,\n    \"vocab_size\": 30522,\n    \"encoder_width\": 768,\n    \"add_cross_attention\": true,\n    \"add_tag_cross_attention\": false\n  }"
  },
  {
    "path": "ram/configs/swin/config_swinB_384.json",
    "content": "{\n    \"ckpt\": \"pretrain_model/swin_base_patch4_window7_224_22k.pth\",\n    \"vision_width\": 1024,\n    \"image_res\": 384,\n    \"window_size\": 12,\n    \"embed_dim\": 128,\n    \"depths\": [ 2, 2, 18, 2 ],\n    \"num_heads\": [ 4, 8, 16, 32 ]\n  }"
  },
  {
    "path": "ram/configs/swin/config_swinL_384.json",
    "content": "{\n    \"ckpt\": \"pretrain_model/swin_large_patch4_window12_384_22k.pth\",\n    \"vision_width\": 1536,\n    \"image_res\": 384,\n    \"window_size\": 12,\n    \"embed_dim\": 192,\n    \"depths\": [ 2, 2, 18, 2 ],\n    \"num_heads\": [ 6, 12, 24, 48 ]\n  }"
  },
  {
    "path": "ram/configs/swin/config_swinL_444.json",
    "content": "{\n    \"ckpt\": \"pretrain_model/swin_large_patch4_window12_384_22k.pth\",\n    \"vision_width\": 1536,\n    \"image_res\": 444,\n    \"window_size\": 12,\n    \"embed_dim\": 192,\n    \"depths\": [ 2, 2, 18, 2 ],\n    \"num_heads\": [ 6, 12, 24, 48 ]\n  }"
  },
  {
    "path": "ram/data/ram_tag_list.txt",
    "content": "3D CG rendering\n3D glasses\nabacus\nabalone\nmonastery\nbelly\nacademy\naccessory\naccident\naccordion\nacorn\nacrylic paint\nact\naction\naction film\nactivity\nactor\nadaptation\nadd\nadhesive tape\nadjust\nadult\nadventure\nadvertisement\nantenna\naerobics\nspray can\nafro\nagriculture\naid\nair conditioner\nair conditioning\nair sock\naircraft cabin\naircraft model\nair field\nair line\nairliner\nairman\nplane\nairplane window\nairport\nairport runway\nairport terminal\nairship\nairshow\naisle\nalarm\nalarm clock\nmollymawk\nalbum\nalbum cover\nalcohol\nalcove\nalgae\nalley\nalmond\naloe vera\nalp\nalpaca\nalphabet\ngerman shepherd\naltar\namber\nambulance\nbald eagle\nAmerican shorthair\namethyst\namphitheater\namplifier\namusement park\namusement ride\nanchor\nancient\nanemone\nangel\nangle\nanimal\nanimal sculpture\nanimal shelter\nanimation\nanimation film\nanimator\nanime\nankle\nanklet\nanniversary\ntrench coat\nant\nantelope\nantique\nantler\nanvil\napartment\nape\napp\napp icon\nappear\nappearance\nappetizer\napplause\napple\napple juice\napple pie\napple tree\napplesauce\nappliance\nappointment\napproach\napricot\napron\naqua\naquarium\naquarium fish\naqueduct\narcade\narcade machine\narch\narch bridge\narchaelogical excavation\narchery\narchipelago\narchitect\narchitecture\narchive\narchway\narea\narena\nargument\narm\narmadillo\narmband\narmchair\narmoire\narmor\narmy\narmy base\narmy tank\narray\narrest\narrow\nart\nart exhibition\nart gallery\nart print\nart school\nart studio\nart vector illustration\nartichoke\narticle\nartifact\nartist\nartists loft\nash\nashtray\nasia temple\nasparagus\nasphalt road\nassemble\nassembly\nassembly line\nassociation\nastronaut\nastronomer\nathlete\nathletic\natlas\natm\natmosphere\natrium\nattach\nfighter jet\nattend\nattraction\natv\neggplant\nauction\naudi\naudio\nauditorium\naurora\nauthor\nauto factory\nauto mechanic\nauto part\nauto show\nauto showroom\ncar battery\nautomobile make\nautomobile model\nmotor vehicle\nautumn\nautumn forest\nautumn leave\nautumn park\nautumn tree\navatar\navenue\naviator sunglasses\navocado\naward\naward ceremony\naward winner\nshed\nax\nazalea\nbaboon\nbaby\nbaby bottle\nbaby carriage\nbaby clothe\nbaby elephant\nbaby food\nbaby seat\nbaby shower\nback\nbackdrop\nbacklight\nbackpack\nbackyard\nbacon\nbadge\nbadger\nbadlands\nbadminton\nbadminton racket\nbag\nbagel\nbagpipe\nbaguette\nbait\nbaked goods\nbaker\nbakery\nbaking\nbaking sheet\nbalance\nbalance car\nbalcony\nball\nball pit\nballerina\nballet\nballet dancer\nballet skirt\nballoon\nballoon arch\nbaseball player\nballroom\nbamboo\nbamboo forest\nbanana\nbanana bread\nbanana leaf\nbanana tree\nband\nband aid\nbandage\nheadscarf\nbandeau\nbangs\nbracelet\nbalustrade\nbanjo\nbank\nbank card\nbank vault\nbanknote\nbanner\nbanquet\nbanquet hall\nbanyan tree\nbaozi\nbaptism\nbar\nbar code\nbar stool\nbarbecue\nbarbecue grill\nbarbell\nbarber\nbarber shop\nbarbie\nbarge\nbarista\nbark\nbarley\nbarn\nbarn owl\nbarn door\nbarrel\nbarricade\nbarrier\nhandcart\nbartender\nbaseball\nbaseball base\nbaseball bat\nbaseball hat\nbaseball stadium\nbaseball game\nbaseball glove\nbaseball pitcher\nbaseball team\nbaseball uniform\nbasement\nbasil\nbasin\nbasket\nbasket container\nbasketball\nbasketball backboard\nbasketball coach\nbasketball court\nbasketball game\nbasketball hoop\nbasketball player\nbasketball stadium\nbasketball team\nbass\nbass guitar\nbass horn\nbassist\nbat\nbath\nbath heater\nbath mat\nbath towel\nswimwear\nbathrobe\nbathroom\nbathroom accessory\nbathroom cabinet\nbathroom door\nbathroom mirror\nbathroom sink\ntoilet paper\nbathroom window\nbatman\nwand\nbatter\nbattery\nbattle\nbattle rope\nbattleship\nbay\nbay bridge\nbay window\nbayberry\nbazaar\nbeach\nbeach ball\nbeach chair\nbeach house\nbeach hut\nbeach towel\nbeach volleyball\nlighthouse\nbead\nbeagle\nbeak\nbeaker\nbeam\nbean\nbean bag chair\nbeanbag\nbear\nbear cub\nbeard\nbeast\nbeat\nbeautiful\nbeauty\nbeauty salon\nbeaver\nbed\nbedcover\nbed frame\nbedroom\nbedding\nbedpan\nbedroom window\nbedside lamp\nbee\nbeech tree\nbeef\nbeekeeper\nbeeper\nbeer\nbeer bottle\nbeer can\nbeer garden\nbeer glass\nbeer hall\nbeet\nbeetle\nbeige\nclock\nbell pepper\nbell tower\nbelt\nbelt buckle\nbench\nbend\nbengal tiger\nbento\nberet\nberry\nberth\nbeverage\nbib\nbibimbap\nbible\nbichon\nbicycle\nbicycle helmet\nbicycle wheel\nbiker\nbidet\nbig ben\nbike lane\nbike path\nbike racing\nbike ride\nbikini\nbikini top\nbill\nbillard\nbillboard\nbilliard table\nbin\nbinder\nbinocular\nbiology laboratory\nbiplane\nbirch\nbirch tree\nbird\nbird bath\nbird feeder\nbird house\nbird nest\nbirdbath\nbird cage\nbirth\nbirthday\nbirthday cake\nbirthday candle\nbirthday card\nbirthday party\nbiscuit\nbishop\nbison\nbit\nbite\nblack\nblack sheep\nblackberry\nblackbird\nblackboard\nblacksmith\nblade\nblanket\nsports coat\nbleacher\nblender\nblessing\nblind\neye mask\nflasher\nsnowstorm\nblock\nblog\nblood\nbloom\nblossom\nblouse\nblow\nhair drier\nblowfish\nblue\nblue artist\nblue jay\nblue sky\nblueberry\nbluebird\npig\nboard\nboard eraser\nboard game\nboardwalk\nboat\nboat deck\nboat house\npaddle\nboat ride\nbobfloat\nbobcat\nbody\nbodyboard\nbodybuilder\nboiled egg\nboiler\nbolo tie\nbolt\nbomb\nbomber\nbonasa umbellu\nbone\nbonfire\nbonnet\nbonsai\nbook\nbook cover\nbookcase\nfolder\nbookmark\nbookshelf\nbookstore\nboom microphone\nboost\nboot\nborder\nBorder collie\nbotanical garden\nbottle\nbottle cap\nbottle opener\nbottle screw\nbougainvillea\nboulder\nbouquet\nboutique\nboutique hotel\nbow\nbow tie\nbow window\nbowl\nbowling\nbowling alley\nbowling ball\nbowling equipment\nbox\nbox girder bridge\nbox turtle\nboxer\nunderdrawers\nboxing\nboxing glove\nboxing ring\nboy\nbrace\nbracket\nbraid\nbrain\nbrake\nbrake light\nbranch\nbrand\nbrandy\nbrass\nbrass plaque\nbread\nbreadbox\nbreak\nbreakfast\nseawall\nchest\nbrewery\nbrick\nbrick building\nwall\nbrickwork\nwedding dress\nbride\ngroom\nbridesmaid\nbridge\nbridle\nbriefcase\nbright\nbrim\nbroach\nbroadcasting\nbroccoli\nbronze\nbronze medal\nbronze sculpture\nbronze statue\nbrooch\ncreek\nbroom\nbroth\nbrown\nbrown bear\nbrownie\nbrunch\nbrunette\nbrush\ncoyote\nbrussels sprout\nbubble\nbubble gum\nbubble tea\nbucket cabinet\nshield\nbud\nbuddha\nbuffalo\nbuffet\nbug\nbuild\nbuilder\nbuilding\nbuilding block\nbuilding facade\nbuilding material\nlamp\nbull\nbulldog\nbullet\nbullet train\nbulletin board\nbulletproof vest\nbullfighting\nmegaphone\nbullring\nbumblebee\nbumper\nroll\nbundle\nbungee\nbunk bed\nbunker\nbunny\nbuoy\nbureau\nburial chamber\nburn\nburrito\nbus\nbus driver\nbus interior\nbus station\nbus stop\nbus window\nbush\nbusiness\nbusiness card\nbusiness executive\nbusiness suit\nbusiness team\nbusiness woman\nbusinessman\nbust\nbutcher\nbutchers shop\nbutte\nbutter\ncream\nbutterfly\nbutterfly house\nbutton\nbuttonwood\nbuy\ntaxi\ncabana\ncabbage\ncabin\ncabin car\ncabinet\ncabinetry\ncable\ncable car\ncactus\ncafe\ncanteen\ncage\ncake\ncake stand\ncalculator\ncaldron\ncalendar\ncalf\ncall\nphone box\ncalligraphy\ncalm\ncamcorder\ncamel\ncamera\ncamera lens\ncamouflage\ncamp\ncamper\ncampfire\ncamping\ncampsite\ncampus\ncan\ncan opener\ncanal\ncanary\ncancer\ncandle\ncandle holder\ncandy\ncandy bar\ncandy cane\ncandy store\ncane\njar\ncannon\ncanopy\ncanopy bed\ncantaloupe\ncantilever bridge\ncanvas\ncanyon\ncap\ncape\ncape cod\ncappuccino\ncapsule\ncaptain\ncapture\ncar\ncar dealership\ncar door\ncar interior\ncar logo\ncar mirror\nparking lot\ncar seat\ncar show\ncar wash\ncar window\ncaramel\ncard\ncard game\ncardboard\ncardboard box\ncardigan\ncardinal\ncargo\ncargo aircraft\ncargo ship\ncaribbean\ncarnation\ncarnival\ncarnivore\ncarousel\ncarp\ncarpenter\ncarpet\nslipper\nhouse finch\ncoach\ndalmatian\naircraft carrier\ncarrot\ncarrot cake\ncarry\ncart\ncarton\ncartoon\ncartoon character\ncartoon illustration\ncartoon style\ncarve\ncase\ncash\ncashew\ncasino\ncasserole\ncassette\ncassette deck\nplaster bandage\ncasting\ncastle\ncat\ncat bed\ncat food\ncat furniture\ncat tree\ncatacomb\ncatamaran\ncatamount\ncatch\ncatcher\ncaterpillar\ncatfish\ncathedral\ncattle\ncatwalk\ncatwalk show\ncauliflower\ncave\ncaviar\nCD\nCD player\ncedar\nceiling\nceiling fan\ncelebrate\ncelebration\ncelebrity\ncelery\ncello\nsmartphone\ncement\ngraveyard\ncenterpiece\ncentipede\nceramic\nceramic tile\ncereal\nceremony\ncertificate\nchain\nchain saw\nchair\nchairlift\ndaybed\nchalet\nchalice\nchalk\nchamber\nchameleon\nchampagne\nchampagne flute\nchampion\nchampionship\nchandelier\nchanging table\nchannel\nchap\nchapel\ncharacter sculpture\ncharcoal\ncharge\ncharger\nchariot\ncharity\ncharity event\ncharm\ngraph\nchase\nchassis\ncheck\ncheckbook\nchessboard\nchecklist\ncheer\ncheerlead\ncheese\ncheeseburger\ncheesecake\ncheetah\nchef\nchemical compound\nchemist\nchemistry\nchemistry lab\ncheongsam\ncherry\ncherry blossom\ncherry tomato\ncherry tree\nchess\nchestnut\nchicken\nchicken breast\nchicken coop\nchicken salad\nchicken wing\ngarbanzo\nchiffonier\nchihuahua\nchild\nchild actor\nchilds room\nchile\nchili dog\nchimney\nchimpanzee\nchinaware\nchinese cabbage\nchinese garden\nchinese knot\nchinese rose\nchinese tower\nchip\nchipmunk\nchisel\nchocolate\nchocolate bar\nchocolate cake\nchocolate chip\nchocolate chip cookie\nchocolate milk\nchocolate mousse\ntruffle\nchoir\nkitchen knife\ncutting board\nchopstick\nchristmas\nchristmas ball\nchristmas card\nchristmas decoration\nchristmas dinner\nchristmas eve\nchristmas hat\nchristmas light\nchristmas market\nchristmas ornament\nchristmas tree\nchrysanthemum\nchurch\nchurch tower\ncider\ncigar\ncigar box\ncigarette\ncigarette case\nwaistband\ncinema\nphotographer\ncinnamon\ncircle\ncircuit\ncircuit board\ncircus\nwater tank\ncitrus fruit\ncity\ncity bus\ncity hall\ncity nightview\ncity park\ncity skyline\ncity square\ncity street\ncity wall\ncity view\nclam\nclarinet\nclasp\nclass\nclassic\nclassroom\nclavicle\nclaw\nclay\npottery\nclean\nclean room\ncleaner\ncleaning product\nclear\ncleat\nclementine\nclient\ncliff\nclimb\nclimb mountain\nclimber\nclinic\nclip\nclip art\nclipboard\nclipper\nclivia\ncloak\nclogs\nclose-up\ncloset\ncloth\nclothe\nclothing\nclothespin\nclothesline\nclothing store\ncloud\ncloud forest\ncloudy\nclover\njoker\nclown fish\nclub\nclutch\nclutch bag\ncoal\ncoast\ncoat\ncoatrack\ncob\ncock\ncockatoo\ncocker\ncockpit\nroach\ncocktail\ncocktail dress\ncocktail shaker\ncocktail table\ncocoa\ncoconut\ncoconut tree\ncoffee\ncoffee bean\ncoffee cup\ncoffee machine\ncoffee shop\ncoffeepot\ncoffin\ncognac\nspiral\ncoin\ncoke\ncolander\ncold\nslaw\ncollaboration\ncollage\ncollection\ncollege student\nsheepdog\ncrash\ncolor\ncoloring book\ncoloring material\npony\npillar\ncomb\ncombination lock\ncomic\ncomedy\ncomedy film\ncomet\ncomfort\ncomfort food\ncomic book\ncomic book character\ncomic strip\ncommander\ncommentator\ncommunity\ncommuter\ncompany\ncompass\ncompete\ncontest\ncompetitor\ncomposer\ncomposition\ncompost\ncomputer\ncomputer box\ncomputer chair\ncomputer desk\nkeyboard\ncomputer monitor\ncomputer room\ncomputer screen\ncomputer tower\nconcept car\nconcert\nconcert hall\nconch\nconcrete\ncondiment\ncondom\ncondominium\nconductor\ncone\nmeeting\nconference center\nconference hall\nmeeting room\nconfetti\nconflict\nconfluence\nconnect\nconnector\nconservatory\nconstellation\nconstruction site\nconstruction worker\ncontain\ncontainer\ncontainer ship\ncontinent\nprofile\ncontract\ncontrol\ncontrol tower\nconvenience store\nconvention\nconversation\nconverter\nconvertible\ntransporter\ncook\ncooking\ncooking spray\ncooker\ncool\ncooler\ncopper\ncopy\ncoral\ncoral reef\nrope\ncorded phone\nliquor\ncorgi\ncork\ncorkboard\ncormorant\ncorn\ncorn field\ncornbread\ncorner\ntrumpet\ncornice\ncornmeal\ncorral\ncorridor\ncorset\ncosmetic\ncosmetics brush\ncosmetics mirror\ncosplay\ncostume\ncostumer film designer\ninfant bed\ncottage\ncotton\ncotton candy\ncouch\ncountdown\ncounter\ncounter top\ncountry artist\ncountry house\ncountry lane\ncountry pop artist\ncountryside\ncoupe\ncouple\ncouple photo\ncourgette\ncourse\ncourt\ncourthouse\ncourtyard\ncousin\ncoverall\ncow\ncowbell\ncowboy\ncowboy boot\ncowboy hat\ncrab\ncrabmeat\ncrack\ncradle\ncraft\ncraftsman\ncranberry\ncrane\ncrape\ncrapper\ncrate\ncrater lake\nlobster\ncrayon\ncream cheese\ncream pitcher\ncreate\ncreature\ncredit card\ncrescent\ncroissant\ncrest\ncrew\ncricket\ncricket ball\ncricket team\ncricketer\ncrochet\ncrock pot\ncrocodile\ncrop\ncrop top\ncross\ncrossbar\ncrossroad\ncrosstalk\ncrosswalk\ncrouton\ncrow\ncrowbar\ncrowd\ncrowded\ncrown\ncrt screen\ncrucifix\ncruise\ncruise ship\ncruiser\ncrumb\ncrush\ncrutch\ncrystal\ncub\ncube\ncucumber\ncue\ncuff\ncufflink\ncuisine\nfarmland\ncup\ncupcake\ncupid\ncurb\ncurl\nhair roller\ncurrant\ncurrency\ncurry\ncurtain\ncurve\npad\ncustomer\ncut\ncutlery\ncycle\ncycling\ncyclone\ncylinder\ncymbal\ncypress\ncypress tree\ndachshund\ndaffodil\ndagger\ndahlia\ndaikon\ndairy\ndaisy\ndam\ndamage\ndamp\ndance\ndance floor\ndance room\ndancer\ndandelion\ndark\ndarkness\ndart\ndartboard\ndashboard\ndate\ndaughter\ndawn\nday bed\ndaylight\ndeadbolt\ndeath\ndebate\ndebris\ndecanter\ndeck\ndecker bus\ndecor\ndecorate\ndecorative picture\ndeer\ndefender\ndeity\ndelicatessen\ndeliver\ndemolition\nmonster\ndemonstration\nden\ndenim jacket\ndentist\ndepartment store\ndepression\nderby\ndermopathy\ndesert\ndesert road\ndesign\ndesigner\ntable\ntable lamp\ndesktop\ndesktop computer\ndessert\ndestruction\ndetective\ndetergent\ndew\ndial\ndiamond\ndiaper\ndiaper bag\njournal\ndie\ndiet\nexcavator\nnumber\ndigital clock\ndill\ndinner\nrowboat\ndining room\ndinner party\ndinning table\ndinosaur\ndip\ndiploma\ndirect\ndirector\ndirt\ndirt bike\ndirt field\ndirt road\ndirt track\ndisaster\ndisciple\ndisco\ndisco ball\ndiscotheque\ndisease\nplate\ndish antenna\ndish washer\ndishrag\ndishes\ndishsoap\nDisneyland\ndispenser\ndisplay\ndisplay window\ntrench\ndive\ndiver\ndiving board\npaper cup\ndj\ndoberman\ndock\ndoctor\ndocument\ndocumentary\ndog\ndog bed\ndog breed\ndog collar\ndog food\ndog house\ndoll\ndollar\ndollhouse\ndolly\ndolphin\ndome\ndomicile\ndomino\ndonkey\ndonut\ndoodle\ndoor\ndoor handle\ndoormat\ndoorplate\ndoorway\ndormitory\ndough\ndowntown\ndozer\ndrag\ndragon\ndragonfly\ndrain\ndrama\ndrama film\ndraw\ndrawer\ndrawing\ndrawing pin\npigtail\ndress\ndress hat\ndress shirt\ndress shoe\ndress suit\ndresser\ndressing room\ndribble\ndrift\ndriftwood\ndrill\ndrink\ndrinking water\ndrive\ndriver\ndriveway\ndrone\ndrop\ndroplight\ndropper\ndrought\nmedicine\npharmacy\ndrum\ndrummer\ndrumstick\ndry\nduchess\nduck\nduckbill\nduckling\nduct tape\ndude\nduet\nduffel\ncanoe\ndumbbell\ndumpling\ndune\ndunk\ndurian\ndusk\ndust\ngarbage truck\ndustpan\nduvet\nDVD\ndye\neagle\near\nearmuff\nearphone\nearplug\nearring\nearthquake\neasel\neaster\neaster bunny\neaster egg\neat\nrestaurant\neclair\neclipse\necosystem\nedit\neducation\neducator\neel\negg\negg roll\negg tart\neggbeater\negret\nEiffel tower\nelastic band\nsenior\nelectric chair\nelectric drill\nelectrician\nelectricity\nelectron\nelectronic\nelephant\nelevation map\nelevator\nelevator car\nelevator door\nelevator lobby\nelevator shaft\nembankment\nembassy\nembellishment\nember\nemblem\nembroidery\nemerald\nemergency\nemergency service\nemergency vehicle\nemotion\nEmpire State Building\nenamel\nenclosure\nside table\nenergy\nengagement\nengagement ring\nengine\nengine room\nengineer\nengineering\nenglish shorthair\nensemble\nenter\nentertainer\nentertainment\nentertainment center\nentrance\nentrance hall\nenvelope\nequestrian\nequipment\neraser\nerhu\nerosion\nescalator\nescargot\nespresso\nestate\nestuary\neucalyptus tree\nevening\nevening dress\nevening light\nevening sky\nevening sun\nevent\nevergreen\newe\nexcavation\nexercise\nexhaust hood\nexhibition\nexit\nexplorer\nexplosion\nextension cord\nextinguisher\nextractor\nextrude\neye\neye shadow\neyebrow\neyeliner\nfabric\nfabric store\nfacade\nface\nface close-up\nface powder\nface towel\nfacial tissue holder\nfacility\nfactory\nfactory workshop\nfair\nfairground\nfairy\nfalcon\nfall\nfamily\nfamily car\nfamily photo\nfamily room\nfan\nfang\nfarm\nfarmer\nfarmer market\nfarmhouse\nfashion\nfashion accessory\nfashion designer\nfashion girl\nfashion illustration\nfashion look\nfashion model\nfashion show\nfast food\nfastfood restaurant\nfather\nfaucet\nfault\nfauna\nfawn\nfax\nfeast\nfeather\nfedora\nfeed\nfeedbag\nfeeding\nfeeding chair\nfeline\nmountain lion\nfence\nfender\nfern\nferret\nferris wheel\nferry\nfertilizer\nfestival\nfiber\nfiction\nfiction book\nfield\nfield road\nfig\nfight\nfigure skater\nfigurine\nfile\nfile photo\nfile cabinet\nfill\nfilm camera\nfilm director\nfilm format\nfilm premiere\nfilm producer\nfilming\nfilter\nfin\nhand\nfinish line\nfir\nfir tree\nfire\nfire alarm\nfire department\nfire truck\nfire escape\nfire hose\nfire pit\nfire station\nfirecracker\nfireman\nfireplace\nfirework\nfirework display\nfirst-aid kit\nfish\nfish boat\nfish market\nfish pond\nfishbowl\nfisherman\nfishing\nfishing boat\nfishing net\nfishing pole\nfishing village\nfitness\nfitness course\nfive\nfixture\nfjord\nflag\nflag pole\nflake\nflame\nflamingo\nflannel\nflap\nflare\nflash\nflask\nflat\nflatfish\nflavor\nflea\nflea market\nfleet\nflight\nflight attendant\nflip\nflip-flop\nflipchart\nfloat\nflock\nflood\nfloor\nfloor fan\nfloor mat\nfloor plan\nfloor window\nfloral arrangement\nflorist\nfloss\nflour\nflow\nflower\nflower basket\nflower bed\nflower box\nflower field\nflower girl\nflower market\nfluid\nflush\nflute\nfly\nfly fishing\nflyer\nhorse\nfoam\nfog\nfoggy\nfoie gra\nfoil\nfolding chair\nleaf\nfolk artist\nfolk dance\nfolk rock artist\nfondant\nhotpot\nfont\nfood\nfood coloring\nfood court\nfood processor\nfood stand\nfood truck\nfoosball\nfoot\nfoot bridge\nfootball\nfootball coach\nfootball college game\nfootball match\nfootball field\nfootball game\nfootball helmet\nfootball player\nfootball stadium\nfootball team\npath\nfootprint\nfootrest\nfootstall\nfootwear\nforbidden city\nford\nforehead\nforest\nforest fire\nforest floor\nforest path\nforest road\nforge\nfork\nforklift\nform\nformal garden\nformation\nformula 1\nfort\nfortification\nforward\nfossil\nfoundation\nfountain\nfountain pen\nfox\nframe\nfreckle\nhighway\nlorry\nFrench\nFrench bulldog\nFrench fries\nFrench toast\nfreshener\nfridge\nfried chicken\nfried egg\nfried rice\nfriendship\nfrisbee\nfrog\nfrost\nfrosting\nfrosty\nfrozen\nfruit\nfruit cake\nfruit dish\nfruit market\nfruit salad\nfruit stand\nfruit tree\nfruits shop\nfry\nfrying pan\nfudge\nfuel\nfume hood\nfun\nfuneral\nfungi\nfunnel\nfur\nfur coat\nfurniture\nfuton\ngadget\nmuzzle\ngalaxy\ngallery\ngame\ngame board\ngame controller\nham\ngang\ngarage\ngarage door\ngarage kit\ngarbage\ngarden\ngarden asparagus\ngarden hose\ngarden spider\ngardener\ngardening\ngarfield\ngargoyle\nwreath\ngarlic\ngarment\ngas\ngas station\ngas stove\ngasmask\ncollect\ngathering\ngauge\ngazebo\ngear\ngecko\ngeisha\ngel\ngeneral store\ngenerator\ngeranium\nghost\ngift\ngift bag\ngift basket\ngift box\ngift card\ngift shop\ngift wrap\ngig\ngin\nginger\ngingerbread\ngingerbread house\nginkgo tree\ngiraffe\ngirl\ngive\nglacier\ngladiator\nglass bead\nglass bottle\nglass bowl\nglass box\nglass building\nglass door\nglass floor\nglass house\nglass jar\nglass plate\nglass table\nglass vase\nglass wall\nglass window\nglasses\nglaze\nglider\nearth\nglove\nglow\nglue pudding\ngo\ngo for\ngoal\ngoalkeeper\ngoat\ngoat cheese\ngobi\ngoggles\ngold\ngold medal\nGolden Gate Bridge\ngolden retriever\ngoldfish\ngolf\ngolf cap\ngolf cart\ngolf club\ngolf course\ngolfer\ngoose\ngorilla\ngothic\ngourd\ngovernment\ngovernment agency\ngown\ngraduate\ngraduation\ngrain\ngrampus\ngrand prix\ngrandfather\ngrandmother\ngrandparent\ngranite\ngranola\ngrape\ngrapefruit\nwine\ngrass\ngrasshopper\ngrassland\ngrassy\ngrater\ngrave\ngravel\ngravestone\ngravy\ngravy boat\ngray\ngraze\ngrazing\ngreen\ngreenery\ngreet\ngreeting\ngreeting card\ngreyhound\ngrid\ngriddle\ngrill\ngrille\ngrilled eel\ngrind\ngrinder\ngrits\ngrocery bag\ngrotto\nground squirrel\ngroup\ngroup photo\ngrove\ngrow\nguacamole\nguard\nguard dog\nguest house\nguest room\nguide\nguinea pig\nguitar\nguitarist\ngulf\ngull\ngun\ngundam\ngurdwara\nguzheng\ngym\ngymnast\nhabitat\nhacker\nhail\nhair\nhair color\nhair spray\nhairbrush\nhaircut\nhairgrip\nhairnet\nhairpin\nhairstyle\nhalf\nhall\nhalloween\nhalloween costume\nhalloween pumpkin\nhalter top\nhamburg\nhamburger\nhami melon\nhammer\nhammock\nhamper\nhamster\nhand dryer\nhand glass\nhand towel\nhandbag\nhandball\nhandcuff\nhandgun\nhandkerchief\nhandle\nhandsaw\nhandshake\nhandstand\nhandwriting\nhanfu\nhang\nhangar\nhanger\nhappiness\nharbor\nharbor seal\nhard rock artist\nhardback book\nsafety helmet\nhardware\nhardware store\nhardwood\nhardwood floor\nmouth organ\npipe organ\nharpsichord\nharvest\nharvester\nhassock\nhat\nhatbox\nhautboy\nhawthorn\nhay\nhayfield\nhazelnut\nhead\nhead coach\nheadlight\nheadboard\nheaddress\nheadland\nheadquarter\nhearing\nheart\nheart shape\nheat\nheater\nheather\nhedge\nhedgehog\nheel\nhelicopter\nheliport\nhelmet\nhelp\nhen\nhenna\nherb\nherd\nhermit crab\nhero\nheron\nhibiscus\nhibiscus flower\nhide\nhigh bar\nhigh heel\nhighland\nhighlight\nhike\nhiker\nhiking boot\nhiking equipment\nhill\nhill country\nhill station\nhillside\nhindu temple\nhinge\nhip\nhip hop artist\nhippo\nhistorian\nhistoric\nhistory\nhockey\nhockey arena\nhockey game\nhockey player\nhockey stick\nhoe\nhole\nvacation\nholly\nholothurian\nhome\nhome appliance\nhome base\nhome decor\nhome interior\nhome office\nhome theater\nhomework\nhummus\nhoney\nbeehive\nhoneymoon\nhood\nhoodie\nhook\njump\nhorizon\nhornbill\nhorned cow\nhornet\nhorror\nhorror film\nhorse blanket\nhorse cart\nhorse farm\nhorse ride\nhorseback\nhorseshoe\nhose\nhospital\nhospital bed\nhospital room\nhost\ninn\nhot\nhot air balloon\nhot dog\nhot sauce\nhot spring\nhotel\nhotel lobby\nhotel room\nhotplate\nhourglass\nhouse\nhouse exterior\nhouseplant\nhoverboard\nhowler\nhuddle\nhug\nhula hoop\nperson\nhumidifier\nhummingbird\nhumpback whale\nhunt\nhunting lodge\nhurdle\nhurricane\nhusky\nhut\nhyaena\nhybrid\nhydrangea\nhydrant\nseaplane\nice\nice bag\npolar bear\nice cave\nicecream\nice cream cone\nice cream parlor\nice cube\nice floe\nice hockey player\nice hockey team\nlollipop\nice maker\nrink\nice sculpture\nice shelf\nskate\nice skating\niceberg\nicicle\nicing\nicon\nid photo\nidentity card\nigloo\nlight\niguana\nilluminate\nillustration\nimage\nimpala\nincense\nindependence day\nindividual\nindoor\nindoor rower\ninduction cooker\nindustrial area\nindustry\ninfantry\ninflatable boat\ninformation desk\ninfrastructure\ningredient\ninhalator\ninjection\ninjury\nink\ninking pad\ninlet\ninscription\ninsect\ninstall\ninstrument\ninsulated cup\ninteraction\ninterior design\nwebsite\nintersection\ninterview\ninvertebrate\ninvitation\nipad\niphone\nipod\niris\niron\nironing board\nirrigation system\nisland\nislet\nisopod\nivory\nivy\nizakaya\njack\njackcrab\njacket\njacuzzi\njade\njaguar\njail cell\njam\njapanese garden\njasmine\njaw\njay\njazz\njazz artist\njazz fusion artist\njeans\njeep\njelly\njelly bean\njellyfish\njet\nmotorboat\njewel\njewellery\njewelry shop\njigsaw puzzle\nrickshaw\njockey\njockey cap\njog\njoint\njournalist\njoystick\njudge\njug\njuggle\njuice\njuicer\njujube\njump rope\njumpsuit\njungle\njunkyard\nkale\nkaleidoscope\nkangaroo\nkaraoke\nkarate\nkarting\nkasbah\nkayak\nkebab\nkey\nkeycard\nkhaki\nkick\nkilt\nkimono\nkindergarden classroom\nkindergarten\nking\nking crab\nkiss\nkit\nkitchen\nkitchen cabinet\nkitchen counter\nkitchen floor\nkitchen hood\nkitchen island\nkitchen sink\nkitchen table\nkitchen utensil\nkitchen window\nkitchenware\nkite\nkiwi\nknee pad\nkneel\nknife\nrider\nknit\nknitting needle\nknob\nknocker\nknot\nkoala\nkoi\nktv\nlaboratory\nlab coat\nlabel\nlabrador\nmaze\nlace\nlace dress\nladder\nladle\nladybird\nlagoon\nlake\nlake district\nlake house\nlakeshore\nlamb\nlamb chop\nlamp post\nlamp shade\nspear\nland\nland vehicle\nlandfill\nlanding\nlanding deck\nlandmark\nlandscape\nlandslide\nlanyard\nlantern\nlap\nlaptop\nlaptop keyboard\nlarva\nlasagne\nlaser\nlash\nlasso\nlatch\nlatex\nlatte\nlaugh\nlaunch\nlaunch event\nlaunch party\nlaundromat\nlaundry\nlaundry basket\nlaundry room\nlava\nlavender\nlawn\nlawn wedding\nlawyer\nlay\nlead\nlead singer\nlead to\nleader\nleak\nlean\nlearn\nleash\nleather\nleather jacket\nleather shoe\nspeech\nlecture hall\nlecture room\nledge\nleftover\nleg\nlegend\nlegging\nlegislative chamber\nlego\nlegume\nlemon\nlemon juice\nlemonade\nlemur\nlens\nlens flare\nlentil\nleopard\nleotard\ntights\nleprechaun\nlesson\nletter\nmailbox\nletter logo\nlettering\nlettuce\nlevel\nlibrary\nlicense\nlicense plate\nlichen\nlick\nlid\nlie\nlife belt\nlife jacket\nlifeboat\nlifeguard\nlift\nlight fixture\nlight show\nlight switch\nlighting\nlightning\nlightning rod\nlilac\nlily\nlimb\nlime\nlimestone\nlimo\nline\nline art\nline up\nlinen\nliner\nlion\nlip balm\nlipstick\nliquid\nliquor store\nlist\nlitchi\nlive\nlivestock\nliving room\nliving space\nlizard\nload\nloading dock\nloafer\nhallway\nlocate\nlock\nlock chamber\nlocker\nloft\nlog\nlog cabin\nlogo\nloki\nlong hair\nlongboard\nloom\nloop\nlose\nlottery\nlotus\nlove\nloveseat\nluggage\nlumber\nlumberjack\nlunch\nlunch box\nlush\nluxury\nluxury yacht\nmac\nmacadamia\nmacaque\nmacaroni\nmacaw\nmachete\nmachine\nmachine gun\nmagazine\nmagic\nmagician\nmagnet\nmagnifying glass\nmagnolia\nmagpie\nmahjong\nmahout\nmaid\nchain mail\nmail slot\nmake\nmakeover\nmakeup artist\nmakeup tool\nmallard\nmallard duck\nmallet\nmammal\nmammoth\nman\nmanagement\nmanager\nmanatee\nmandala\nmandarin orange\nmandarine\nmane\nmanga\nmanger\nmango\nmangosteen\nmangrove\nmanhattan\nmanhole\nmanhole cover\nmanicure\nmannequin\nmanor house\nmansion\nmantid\nmantle\nmanufactured home\nmanufacturing\nmanuscript\nmap\nmaple\nmaple leaf\nmaple syrup\nmaraca\nmarathon\nmarble\nmarch\nmarching band\nmare\nmarigold\nmarine\nmarine invertebrate\nmarine mammal\npuppet\nmark\nmarket\nmarket square\nmarket stall\nmarriage\nmartial\nmartial artist\nmartial arts gym\nmartini\nmartini glass\nmascara\nmascot\nmashed potato\nmasher\nmask\nmassage\nmast\nmat\nmatador\nmatch\nmatchbox\nmaterial\nmattress\nmausoleum\nmaxi dress\nmeal\nmeasuring cup\nmeasuring tape\nmeat\nmeatball\nmechanic\nmechanical fan\nmedal\nmedia\nmedical equipment\nmedical image\nmedical staff\nmedicine cabinet\nmedieval\nmedina\nmeditation\nmeerkat\nmeet\nmelon\nmonument\nmenu\nmermaid\nnet\nmess\nmessenger bag\nmetal\nmetal artist\nmetal detector\nmeter\nmezzanine\nmicrophone\nmicroscope\nmicrowave\nmidnight\nmilestone\nmilitary uniform\nmilk\nmilk can\nmilk tea\nmilkshake\nmill\nmine\nminer\nmineral\nmineral water\nminiskirt\nminiature\nminibus\nminister\nminivan\nmint\nmint candy\nmirror\nmiss\nmissile\nmission\nmistletoe\nmix\nmixer\nmixing bowl\nmixture\nmoat\nmobility scooter\nmodel\nmodel car\nmodern\nmodern tower\nmoisture\nmold\nmolding\nmole\nmonarch\nmoney\nmonitor\nmonk\nmonkey\nmonkey wrench\nmonochrome\nmonocycle\nmonster truck\nmoon\nmoon cake\nmoonlight\nmoor\nmoose\nswab\nmoped\nmorning\nmorning fog\nmorning light\nmorning sun\nmortar\nmosaic\nmosque\nmosquito\nmoss\nmotel\nmoth\nmother\nmotherboard\nmotif\nsport\nmotor\nmotorbike\nmotorcycle\nmotorcycle helmet\nmotorcycle racer\nmotorcyclist\nmotorsport\nmound\nmountain\nmountain bike\nmountain biker\nmountain biking\nmountain gorilla\nmountain lake\nmountain landscape\nmountain pass\nmountain path\nmountain range\nmountain river\nmountain snowy\nmountain stream\nmountain view\nmountain village\nmountaineer\nmountaineering bag\nmouse\nmousepad\nmousetrap\nmouth\nmouthwash\nmove\nmovie poster\nmovie ticket\nmower\nmp3 player\nmr\nmud\nmuffin\nmug\nmulberry\nmulch\nmule\nmunicipality\nmural\nmuscle\nmuscle car\nmuseum\nmushroom\nmusic\nmusic festival\nmusic stool\nmusic studio\nmusic video performer\nmusical keyboard\nmusician\nmussel\nmustard\nmythology\nnacho\nnail polish\nnailfile\nnanny\nnapkin\nnarrow\nnational flag\nnativity scene\nnatural history museum\nnature\nnature reserve\nnavigation\nnavratri\nnavy\nnebula\nneck\nneckband\nnecklace\nneckline\nnectar\nnectarine\nneedle\nneighbor\nneighbourhood\nneon\nneon light\nnerve\nnest\nnew year\nnewborn\nnewfoundland\nnewlywed\nnews\nnews conference\nnewsstand\nnight\nnight market\nnight sky\nnight view\nnightclub\nnightstand\nnoodle\nnose\nnoseband\nnote\nnotebook\nnotepad\nnotepaper\nnotice\nnumber icon\nnun\nnurse\nnursery\nnursing home\nnut\nnutcracker\noak\noak tree\noar\noasis\noast house\noatmeal\noats\nobelisk\nobservation tower\nobservatory\nobstacle course\nsea\noctopus\noffer\noffice\noffice building\noffice chair\noffice cubicle\noffice desk\noffice supply\noffice window\nofficer\nofficial\noil\noil lamp\noil painting\noilrig\nokra\nold photo\nolive\nolive oil\nolive tree\nomelet\nonion\nonion ring\nopal\nopen\nopening\nopening ceremony\nopera\nopera house\noperate\noperating room\noperation\noptical shop\norangutan\norange\norange juice\norange tree\norangery\norbit\norchard\norchestra pit\norchid\norder\norganization\norigami\nornament\nosprey\nostrich\notter\nout\noutcrop\noutdoor\nouthouse\nelectric outlet\noutline\noval\noven\noverall\novercoat\noverpass\nowl\noyster\nteething ring\npack\npackage\npaddock\npolice van\npadlock\npaella\npagoda\npain\npaint brush\npainter\npaisley bandanna\npalace\npalette\npaling\npall\npalm tree\npan\npancake\npanda\npanel\npanorama\npansy\npant\npantry\npants\npantyhose\npapaya\npaper\npaper bag\npaper cutter\npaper lantern\npaper plate\npaper towel\npaperback book\npaperweight\nparachute\nparade\nparadise\nparrot\nparamedic\nparaquet\nparasail\nparatrooper\nparchment\nparish\npark\npark bench\nparking\nparking garage\nparking meter\nparking sign\nparliament\nparsley\nparticipant\npartner\npartridge\nparty\nparty hat\npass\npassage\npassbook\npassenger\npassenger ship\npassenger train\npassion fruit\npassport\npasta\npaste\npastry\npasture\npatch\npatient\npattern\npavement\npavilion\npaw\npay\npayphone\npea\npeace\npeach\npeacock\npeak\npeanut\npeanut butter\npear\npearl\npebble\npecan\npedestrian\npedestrian bridge\npedestrian street\npeel\npeeler\npegboard\npegleg\npelican\npen\npenalty kick\npencil\npencil case\npencil sharpener\npencil skirt\npendant\npendulum\npenguin\npeninsula\npennant\npenny\npiggy bank\npeony\npepper\npepper grinder\npeppercorn\npepperoni\nperch\nperform\nperformance\nperformance arena\nperfume\npergola\npersian cat\npersimmon\npersonal care\npersonal flotation device\npest\npet\npet shop\npet store\npetal\npetunia\nchurch bench\npheasant\nphenomenon\nphilosopher\nphone\nphonebook\nrecord player\nphoto\nphoto booth\nphoto frame\nphotography\nphysicist\nphysics laboratory\npianist\npiano\nplectrum\npick up\npickle\npicnic\npicnic area\npicnic basket\npicnic table\npicture\npicture frame\npie\npigeon\npilgrim\ntablet\npillow\npilot\npilot boat\npin\npine\npine cone\npine forest\npine nut\npineapple\ntable tennis table\ntable tennis\npink\npint\npipa\npipe\npipe bowl\npirate\npirate flag\npirate ship\npistachio\nski slope\npocket bread\npitaya\npitbull\npitch\npitcher\npitcher plant\npitchfork\npizza\npizza cutter\npizza pan\npizzeria\nplacard\nplace\nplace mat\nplaid\nplain\nplan\nplanet\nplanet earth\nplank\nplant\nplantation\nplanting\nplaque\nplaster\nplastic\nplasticine\nplateau\nplatform\nplatinum\nplatter\nplay\nplay badminton\nplay baseball\nplay basketball\nplay billiard\nplay football\nplay pong\nplay tennis\nplay volleyball\nplayer\nplayground\nplayhouse\nplaying card\nplaying chess\nplaying golf\nplaying mahjong\nplayingfield\nplaypen\nplayroom\nplaza\nplier\nplot\nplow\nplug\nplug hat\nplum\nplumber\nplumbing fixture\nplume\nplywood\npocket\npocket watch\npocketknife\npod\npodium\npoetry\npoinsettia\npoint\npointer\npoker card\npoker chip\npoker table\npole\npolecat\npolice\npolice car\npolice dog\npolice station\npolitician\npolka dot\npollen\npollution\npolo\npolo neck\npolo shirt\npomegranate\npomeranian\nponcho\npond\nponytail\npoodle\npool\npop\npop artist\npopcorn\npope\npoppy\nporcelain\nporch\npork\nporridge\nportable battery\nportal\nportfolio\nporthole\nportrait\nportrait session\npose\npossum\npost\npost office\nstamp\npostcard\nposter\nposter page\npot\npotato\npotato chip\npotato salad\npotholder\npotty\npouch\npoultry\npound\npour\npowder\npower line\npower plugs and sockets\npower see\npower station\npractice\nPrague Castle\nprayer\npreacher\npremiere\nprescription\nshow\npresentation\npresident\npress room\npressure cooker\npretzel\nprince\nprincess\nprint\nprinted page\nprinter\nprinting\nprison\nproduce\nproduct\nprofession\nprofessional\nprofessor\nproject picture\nprojection screen\nprojector\nprom\npromenade\npropeller\nprophet\nproposal\nprotective suit\nprotest\nprotester\npublication\npublicity portrait\nice hockey\npudding\npuddle\npuff\npuffin\npug\npull\npulpit\npulse\npump\npumpkin\npumpkin pie\npumpkin seed\npunch bag\npunch\nstudent\npurple\npush\nputt\npuzzle\ntower\npyramid\npython\nqr code\nquail\nquarry\nquarter\nquartz\nqueen\nquesadilla\nqueue\nquiche\nquilt\nquilting\nquote\nrabbit\nraccoon\nrace\nrace track\nraceway\nrace car\nracket\nradar\nradiator\nradio\nraft\nrag doll\nrail\nrailcar\nrailroad\nrailroad bridge\nrailway line\nrailway station\nrain\nrain boot\nrainbow\nrainbow trout\nraincoat\nrainforest\nrainy\nraisin\nrake\nram\nramp\nrapeseed\nrapid\nrapper\nraspberry\nrat\nratchet\nraven\nravine\nray\nrazor\nrazor blade\nread\nreading\nreamer\nrear\nrear light\nrear view\nrearview mirror\nreceipt\nreceive\nreception\nrecipe\nrecord\nrecord producer\nrecorder\nrecording studio\nrecreation room\nrecreational vehicle\nrectangle\nrecycling\nrecycling bin\nred\nred carpet\nred flag\nred panda\nred wine\nredwood\nreed\nreef\nreel\nreferee\nreflect\nreflection\nreflector\nregister\nrein\nreindeer\nrelax\nrelease\nrelief\nreligion\nreligious\nrelish\nremain\nremodel\nremote\nremove\nrepair\nrepair shop\nreptile\nrescue\nrescuer\nresearch\nresearcher\nreservoir\nresidence\nresidential neighborhood\nresin\nresort\nresort town\nrestaurant kitchen\nrestaurant patio\nrestroom\nretail\nretriever\nretro\nreveal\nrhinoceros\nrhododendron\nrib\nribbon\nrice\nrice cooker\nrice field\nride\nridge\nriding\nrifle\nrim\nring\nriot\nripple\nrise\nrise building\nriver\nriver bank\nriver boat\nriver valley\nriverbed\nroad\nroad sign\nroad trip\nroadside\nroast chicken\nrobe\nrobin\nrobot\nstone\nrock arch\nrock artist\nrock band\nrock climber\nrock climbing\nrock concert\nrock face\nrock formation\nrocker\nrocket\nrocking chair\nrocky\nrodent\nrodeo\nrodeo arena\nroe\nroe deer\nroller\ncoaster\nroller skate\nroller skates\nrolling pin\nromance\nromantic\nroof\nroof garden\nroom\nroom divider\nroot\nroot beer\nrope bridge\nrosary\nrose\nrosemary\nrosy cloud\nrottweiler\nround table\nrouter\nrow\nrowan\nroyal\nrubber stamp\nrubble\nrubik's cube\nruby\nruffle\nrugby\nrugby ball\nrugby player\nruins\nruler\nrum\nrun\nrunner\nrunning shoe\nrural\nrust\nrustic\nrye\nsack\nsaddle\nsaddlebag\nsafari\nsafe\nsafety vest\nsage\nsail\nsailboat\nsailing\nsailor\nsquirrel monkey\nsake\nsalad\nsalad bowl\nsalamander\nsalami\nsale\nsalmon\nsalon\nsalsa\nsalt\nsalt and pepper shakers\nsalt lake\nsalt marsh\nsalt shaker\nsalute\nsamoyed\nsamurai\nsand\nsand bar\nsand box\nsand castle\nsand sculpture\nsandal\nsandwich\nsanitary napkin\nsanta claus\nsapphire\nsardine\nsari\nsashimi\nsatay\nsatchel\nsatellite\nsatin\nsauce\nsaucer\nsauna\nsausage\nsavanna\nsaw\nsawbuck\nsax\nsaxophonist\nscaffold\nscale\nscale model\nscallop\nscar\nstrawman\nscarf\nscene\nscenery\nschnauzer\nschool\nschool bus\nschool uniform\nschoolhouse\nschooner\nscience\nscience fiction film\nscience museum\nscientist\nscissors\nwall lamp\nscone\nscoop\nscooter\nscore\nscoreboard\nscorpion\nscout\nscrambled egg\nscrap\nscraper\nscratch\nscreen\nscreen door\nscreenshot\nscrew\nscrewdriver\nscroll\nscrub\nscrubbing brush\nsculptor\nsculpture\nsea cave\nsea ice\nsea lion\nsea turtle\nsea urchin\nseabass\nseabed\nseabird\nseafood\nseahorse\nseal\nsea view\nseashell\nseaside resort\nseason\nseat\nseat belt\nseaweed\nsecretary\nsecurity\nsedan\nsee\nseed\nseesaw\nsegway\nselfie\nsell\nseminar\nsense\nsensor\nserver\nserver room\nservice\nset\nsewing machine\nshadow\nshake\nshaker\nshampoo\nshape\nshare\nshark\nsharpener\nsharpie\nshaver\nshaving cream\nshawl\nshear\nshears\nsheep\nsheet\nsheet music\nshelf\nshell\nshellfish\nshelter\nshelve\nshepherd\nsherbert\nshiba inu\nshine\nshipping\nshipping container\nshipwreck\nshipyard\nshirt\nshirtless\nshoal\nshoe\nshoe box\nshoe shop\nshoe tree\nshoot\nshooting basketball guard\nshop window\nshopfront\nshopper\nshopping\nshopping bag\nshopping basket\nshopping cart\nmall\nshopping street\nshore\nshoreline\nshort\nshort hair\nshorts\nshot glass\nshotgun\nshoulder\nshoulder bag\nshovel\nshowcase\nshower\nshower cap\nshower curtain\nshower door\nshower head\nshredder\nshrew\nshrimp\nshrine\nshrub\nshutter\nsiamese\nsiberia\nsibling\nside\nside cabinet\nside dish\nsidecar\nsideline\nsiding\nsign\nsignage\nsignal\nsignature\nsilk\nsilk stocking\nsilo\nsilver\nsilver medal\nsilverware\nsing\nsinge\nsinger\nsink\nsip\nsit\nsitting\nskate park\nskateboard\nskateboarder\nskater\nskating rink\nskeleton\nsketch\nskewer\nski\nski boot\nski equipment\nski jacket\nski lift\nski pole\nski resort\nsnowboard\nskier\nskiing shoes\nskin\nskull\nskullcap\nsky\nsky tower\nskylight\nskyline\nskyscraper\nslalom\nslate\nsleigh\nsleep\nsleeping bag\nsleepwear\nsleeve\nslice\nslide\nslider\nsling\nslope\nslot\nslot machine\nsloth\nslow cooker\nslug\nslum\nsmell\nsmile\nsmoke\nsnack\nsnail\nsnake\nsnapper\nsnapshot\nsnorkel\nsnout\nsnow\nsnow leopard\nsnow mountain\nsnowball\nsnowboarder\nsnowfield\nsnowflake\nsnowman\nsnowmobile\nsnowplow\nsnowshoe\nsnowy\nsoap\nsoap bubble\nsoap dispenser\nsoccer goalkeeper\nsocialite\nsock\nsocket\nsoda\nsoftball\nsoftware\nsolar battery\nsoldier\nsolo\nsolution\nsombrero\nsong\nsound\nsoup\nsoup bowl\nsoupspoon\nsour cream\nsouvenir\nsoybean milk\nspa\nspace\nspace shuttle\nspace station\nspacecraft\nspaghetti\nspan\nwrench\nspark\nsparkle\nsparkler\nsparkling wine\nsparrow\nspatula\nspeaker\nspectator\nspeech bubble\nspeed limit\nspeed limit sign\nspeedboat\nspeedometer\nsphere\nspice\nspice rack\nspider\nspider web\nspike\nspin\nspinach\nspire\nsplash\nsponge\nspoon\nsport association\nsport equipment\nsport team\nsports ball\nsports equipment\nsports meet\nsportswear\ndot\nspray\nspread\nspring\nspring roll\nsprinkle\nsprinkler\nsprout\nspruce\nspruce forest\nsquad\nsquare\nsquash\nsquat\nsqueeze\nsquid\nsquirrel\nwater gun\nstab\nstable\nstack\nstadium\nstaff\nstage\nstage light\nstagecoach\nstain\nstainless steel\nstair\nstairs\nstairwell\nstall\nstallion\nstand\nstanding\nstaple\nstapler\nstar\nstare\nstarfish\nstarfruit\nstarling\nstate park\nstate school\nstation\nstationary bicycle\nstationery\nstatue\nsteak\nsteak knife\nsteam\nsteam engine\nsteam locomotive\nsteam train\nsteamed bread\nsteel\nsteering wheel\nstem\nstencil\nstep stool\nstereo\nstethoscope\nstew\nstick\nstick insect\nsticker\nstill life\nstilt\nstingray\nstir\nstirrer\nstirrup\nsew\nstock\nstocking\nstomach\nstone building\nstone carving\nstone house\nstone mill\nstool\nstop\nstop at\nstop light\nstop sign\nstop watch\ntraffic light\nstorage box\nstorage room\ntank\nstore\nstorefront\nstork\nstorm\nstorm cloud\nstormy\nstove\npoker\nstraddle\nstrainer\nstrait\nstrap\nstraw\nstraw hat\nstrawberry\nstream\nstreet art\nstreet artist\nstreet corner\nstreet dog\nstreet food\nstreet light\nstreet market\nstreet photography\nstreet scene\nstreet sign\nstreet vendor\nstretch\nstretcher\nstrike\nstriker\nstring\nstring cheese\nstrip\nstripe\nstroll\nstructure\nstudio\nstudio shot\nstuff\nstuffed animal\nstuffed toy\nstuffing\nstump\nstunning\nstunt\nstupa\nstyle\nstylus\nsubmarine\nsubmarine sandwich\nsubmarine water\nsuburb\nsubway\nsubway station\nsubwoofer\nsucculent\nsuede\nsugar\nsugar bowl\nsugar cane\nsugar cube\nsuit\nsuite\nsummer\nsummer evening\nsummit\nsun\nsun hat\nsunbathe\nsunday\nsundial\nsunflower\nsunflower field\nsunflower seed\nsunglasses\nsunny\nsunrise\nsunset\nsunshade\nsunshine\nsuper bowl\nsports car\nsuperhero\nsupermarket\nsupermarket shelf\nsupermodel\nsupporter\nsurf\nsurface\nsurfboard\nsurfer\nsurgeon\nsurgery\nsurround\nsushi\nsushi bar\nsuspenders\nsuspension\nsuspension bridge\nsuv\nswallow\nswallowtail butterfly\nswamp\nswan\nswan boat\nsweat pant\nsweatband\nsweater\nsweatshirt\nsweet\nsweet potato\nswim\nswim cap\nswimmer\nswimming hole\nswimming pool\nswing\nswing bridge\nswinge\nswirl\nswitch\nswivel chair\nsword\nswordfish\nsymbol\nsymmetry\nsynagogue\nsyringe\nsyrup\nsystem\nt shirt\nt-shirt\ntabasco sauce\ntabby\ntable tennis racket\ntable top\ntablecloth\ntablet computer\ntableware\ntachometer\ntackle\ntaco\ntae kwon do\ntai chi\ntail\ntailor\ntake\ntakeoff\ntalk\ntambourine\ntan\ntangerine\ntape\ntapestry\ntarmac\ntaro\ntarp\ntart\ntassel\ntaste\ntatami\ntattoo\ntattoo artist\ntavern\ntea\ntea bag\ntea party\ntea plantation\ntea pot\ntea set\nteach\nteacher\nteacup\nteal\nteam photo\nteam presentation\ntear\ntechnician\ntechnology\nteddy\ntee\nteenager\ntelegraph pole\nzoom lens\ntelescope\ntelevision\ntelevision camera\ntelevision room\ntelevision studio\ntemperature\ntemple\ntempura\ntennis\ntennis court\ntennis match\ntennis net\ntennis player\ntennis racket\ntent\ntequila\nterminal\nterrace\nterrain\nterrarium\nterritory\ntest\ntest match\ntest tube\ntext\ntext message\ntextile\ntexture\nthanksgiving\nthanksgiving dinner\ntheater\ntheatre actor\ntherapy\nthermometer\nthermos\nthermos bottle\nthermostat\nthicket\nthimble\nthing\nthinking\nthistle\nthrone\nthrone room\nthrow\nthrow pillow\nthunder\nthunderstorm\nthyme\ntiara\ntick\nticket\nticket booth\ntide pool\ntie\ntiger\ntight\ntile\ntile flooring\ntile roof\ntile wall\ntin\ntinfoil\ntinsel\ntiramisu\ntire\ntissue\ntoast\ntoaster\ntobacco\ntobacco pipe\ntoddler\ntoe\ntofu\ntoilet bowl\ntoilet seat\ntoiletry\ntokyo tower\ntomato\ntomato sauce\ntomato soup\ntomb\ntong\ntongs\ntool\ntoolbox\ntoothbrush\ntoothpaste\ntoothpick\ntopiary garden\ntopping\ntorch\ntornado\ntortilla\ntortoise\ntote bag\ntotem pole\ntotoro\ntoucan\ntouch\ntouchdown\ntour\ntour bus\ntour guide\ntourist\ntourist attraction\ntournament\ntow truck\ntowel\ntowel bar\ntower block\ntower bridge\ntown\ntown square\ntoy\ntoy car\ntoy gun\ntoyshop\ntrack\ntractor\ntrade\ntradition\ntraditional\ntraffic\ntraffic cone\ntraffic congestion\ntraffic jam\ntraffic sign\ntrail\ntrailer\ntrailer truck\ntrain\ntrain bridge\ntrain car\ntrain interior\ntrain track\ntrain window\ntrainer\ntraining\ntraining bench\ntraining ground\ntrolley\ntrampoline\ntransformer\ntransparency\ntravel\ntray\ntreadmill\ntreat\ntree\ntree branch\ntree farm\ntree frog\ntree house\ntree root\ntree trunk\ntrial\ntriangle\ntriathlon\ntribe\ntributary\ntrick\ntricycle\ntrim\ntrio\ntripod\ntrombone\ntroop\ntrophy\ntrophy cup\ntropic\ntrout\ntruck\ntruck driver\ntub\ntube\ntugboat\ntulip\ntuna\ntundra\ntunnel\nturbine\nturkey\nturn\nturnip\nturquoise\nturret\nturtle\ntusk\ntv actor\ntv cabinet\ntv drama\ntv genre\ntv personality\ntv show\ntv sitcom\ntv tower\ntwig\ntwilight\ntwin\ntwine\ntwist\ntype\ntype on\ntypewriter\nukulele\nultraman\numbrella\nunderclothes\nunderwater\nunicorn\nuniform\nuniverse\nuniversity\nup\nurban\nurinal\nurn\nuse\nutensil\nutility room\nvacuum\nvalley\nvalve\nvampire\nvan\nvanilla\nvanity\nvariety\nvase\nvault\nvector cartoon illustration\nvector icon\nvegetable\nvegetable garden\nvegetable market\nvegetation\nvehicle\nveil\nvein\nvelvet\nvending machine\nvendor\nvent\nvespa\nvessel\nvest\nvet\nveteran\nveterinarians office\nviaduct\nvideo\nvideo camera\nvideo game\nvideotape\nview mirror\nvigil\nvilla\nvillage\nvine\nvinegar\nvineyard\nviolence\nviolet\nviolin\nviolinist\nviolist\nvision\nvisor\nvodka\nvolcano\nvolleyball\nvolleyball court\nvolleyball player\nvolunteer\nvoyage\nvulture\nwaffle\nwaffle iron\nwagon\nwagon wheel\nwaist\nwaiter\nwaiting hall\nwaiting room\nwalk\nwalking\nwalking cane\nwall clock\nwallpaper\nwalnut\nwalrus\nwar\nwarehouse\nwarm\nwarning sign\nwarrior\nwarship\nwarthog\nwash\nwasher\nwashing\nwashing machine\nwasp\nwaste\nwaste container\nwatch\nwater\nwater bird\nwater buffalo\nwater cooler\nwater drop\nwater feature\nwater heater\nwater level\nwater lily\nwater park\nwater pipe\nwater purifier\nwater ski\nwater sport\nwater surface\nwater tower\nwatercolor\nwatercolor illustration\nwatercolor painting\nwaterfall\nwatering can\nwatermark overlay stamp\nwatermelon\nwaterproof jacket\nwaterway\nwave\nwax\nweapon\nwear\nweather\nvane\nweb\nwebcam\nwedding\nwedding ring\nwedding bouquet\nwedding cake\nwedding couple\nwedding invitation\nwedding party\nwedding photo\nwedding photographer\nwedding photography\nwedding reception\nwedge\nweed\nweight\nweight scale\nwelder\nwell\nwestern food\nwestern restaurant\nwet\nwet bar\nwet suit\nwetland\nwetsuit\nwhale\nwhale shark\nwheat\nwheat field\nwheel\nwheelchair\nwheelie\nwhipped cream\nwhisk\nwhisker\nwhiskey\nwhistle\nwhite\nwhite house\nwhite wine\nwhiteboard\nwicket\nwide\nwield\nwig\nWii\nWii controller\nwild\nwildebeest\nwildfire\nwildflower\nwildlife\nwillow\nwind\nwind chime\nwind farm\nwind turbine\nwindmill\nwindow\nwindow box\nwindow display\nwindow frame\nwindow screen\nwindow seat\nwindow sill\nwiper\nwindshield\nwindy\nwine bottle\nwine cooler\nwine cabinet\nwine cellar\nwine glass\nwine rack\nwine tasting\nwinery\nwing\nwinter\nwinter melon\nwinter morning\nwinter scene\nwinter sport\nwinter storm\nwire\nwisteria\nwitch\nwitch hat\nwok\nwolf\nwoman\nwood\nwood duck\nwood floor\nwood wall\nwood-burning stove\nwooden spoon\nwoodland\nwoodpecker\nwoodworking plane\nwool\njob\nwork card\nworkbench\nworker\nworkplace\nworkshop\nworld\nworm\nworship\nwound\nwrap\nwrap dress\nwrapping paper\nwrestle\nwrestler\nwrinkle\nwristband\nwrite\nwriter\nwriting\nwriting brush\nwriting desk\nyacht\nyak\nyard\nyellow\nyoga\nyoga mat\nyoghurt\nyoke\nyolk\nyouth\nyouth hostel\nyurt\nzebra\nzebra crossing\nzen garden\nzip\nzipper\nzombie\nzongzi\nzoo"
  },
  {
    "path": "ram/data/ram_tag_list_chinese.txt",
    "content": "三维CG渲染 \n3d眼镜\n算盘 \n鲍鱼 \n修道院 \n肚子 \n学院 \n附件 \n事故 \n手风琴 \n橡子 \n丙烯颜料\n表演\n行动 \n动作电影 \n活动 \n演员 \n改编本\n添加 \n胶带 \n调整 \n成人 \n冒险 \n广告 \n天线 \n有氧运动 \n喷雾罐\n爆炸头\n农业 \n帮助\n空调 \n空调系统\n风向标\n飞机客舱 \n飞机模型 \n机场 \n航线\n客机 \n飞行员 \n飞机 \n飞机窗口 \n机场 \n机场跑道 \n航站楼 \n飞艇 \n航展\n过道 \n警报\n闹钟 \n信天翁 \n唱片\n唱片封面 \n酒精 \n壁龛\n水藻\n胡同/球道\n杏仁 \n芦荟\n高山 \n羊驼 \n字母表\n德国牧羊犬\n圣坛\n琥珀\n救护车 \n秃鹰\n美国短毛猫 \n紫水晶 \n圆形剧场 \n扩音器\n游乐园 \n游乐设施 \n锚 \n古老的 \n海葵 \n天使 \n角 \n动物 \n动物雕塑 \n动物收容所 \n动画片\n动画电影 \n动画师 \n动漫 \n脚踝 \n短袜 \n周年庆\n风衣 \n蚂蚁 \n羚羊 \n古董 \n鹿角 \n铁砧 \n公寓 \n猿 \n应用程序 \n应用图标 \n出现 \n外观 \n开胃菜 \n掌声 \n苹果 \n苹果汁 \n苹果派 \n苹果树 \n苹果酱 \n设备 \n约定\n通道\n杏子\n围裙 \n浅绿色\n水族馆 \n观赏鱼\n渡槽 \n游乐中心\n商场游戏机\n拱门\n拱桥 \n考古现场\n射箭 \n群岛 \n建筑师\n建筑设计\n档案\n拱门 \n地区\n竞技场 \n争论\n手臂 \n穿山甲\n臂章 \n扶手椅 \n衣柜\n盔甲\n军队 \n军事基地 \n坦克 \n阵列\n逮捕 \n箭头 \n艺术 \n艺术展\n美术馆\n艺术印刷品\n艺术学校 \n艺术工作室 \n艺术矢量插图 \n洋蓟 \n文章 \n手工艺品\n艺术家 \n艺术阁楼 \n灰 \n烟灰缸 \n亚洲寺庙 \n芦笋 \n沥青道路\n组装\n集会\n生产流水线\n协会 \n宇航员 \n天文学家 \n运动员 \n运动 \n地图集\n自助取款机 \n大气层\n中庭 \n连接\n战斗机 \n参加 \n吸引力 \n全地形车\n茄子 \n拍卖 \n奥迪汽车\n音频 \n礼堂 \n极光 \n作者 \n汽车厂 \n汽车修理工 \n汽车零件\n车展 \n汽车展厅 \n汽车电池 \n汽车制造\n汽车模型 \n汽车\n秋天 \n秋天的森林 \n秋天的叶子\n秋天的公园 \n秋天的树 \n阿凡达\n林荫大道\n飞行员太阳镜 \n牛油果\n奖品\n颁奖典礼 \n获奖者\n棚\n斧头 \n杜鹃花 \n狒狒 \n婴儿 \n奶瓶 \n婴儿车 \n婴儿衣服 \n小象 \n婴儿食品 \n婴儿座椅\n迎婴派对\n背后/后面\n背景 \n背光 \n背包 \n后院 \n培根 \n徽章 \n獾 \n荒地 \n羽毛球运动\n羽毛球拍 \n袋子\n面包圈\n风笛 \n法棍\n诱饵 \n焙烤食品 \n面包师\n面包店 \n烘焙 \n烤盘 \n平衡 \n平衡车 \n阳台 \n球 \n球池\n芭蕾舞女演员 \n芭蕾舞 \n芭蕾舞演员 \n芭蕾舞裙 \n气球 \n气球拱门 \n棒球手 \n舞厅 \n竹子 \n竹林 \n香蕉 \n香蕉面包 \n香蕉叶子 \n香蕉树 \n乐队 \n创可贴 \n绷带 \n头巾 \n束发带 \n刘海\n手镯 \n栏杆\n五弦琴\n银行 \n银行卡 \n银行金库\n纸币\n横幅/旗帜\n宴会 \n宴会厅 \n榕树\n包子 \n洗礼 \n酒吧 \n条形码 \n高脚凳\n烧烤 \n烧烤架 \n杠铃 \n理发师 \n理发店 \n芭比娃娃 \n驳船 \n咖啡师 \n树皮 \n大麦 \n谷仓 \n仓鸮\n挡光板\n桶 \n路障\n屏障\n手推车 \n酒保 \n棒球 \n棒球基地 \n棒球棒 \n棒球帽 \n棒球场\n棒球比赛 \n棒球手套 \n棒球投手 \n棒球队 \n棒球制服 \n地下室 \n罗勒 \n水盆\n篮子 \n篮子\n篮球 \n篮球篮板 \n篮球教练 \n篮球场 \n篮球比赛 \n篮球框\n篮球运动员 \n篮球馆 \n篮球队 \n贝斯\n低音吉他 \n低音喇叭 \n贝斯手 \n球棒/球拍\n浴室\n水浴加热器\n浴垫 \n浴巾 \n泳装 \n浴袍 \n浴室 \n浴室配件 \n浴室柜 \n浴室门 \n浴室镜子\n浴室水槽 \n卫生纸\n浴室窗户\n蝙蝠侠 \n棒子\n接连猛打/击球员\n电池 \n战斗 \n战绳\n战舰 \n海湾\n海湾大桥 \n凸窗 \n杨梅\n集市 \n海滩 \n沙滩球 \n沙滩椅 \n海滨别墅 \n海滩小屋 \n沙滩毛巾 \n沙滩排球 \n灯塔 \n珠子\n比格犬\n鸟嘴\n烧杯 \n横梁\n豆子\n豆袋椅 \n豆袋 \n熊 \n幼熊 \n胡子 \n野兽 \n击打/击败\n美丽的 \n美丽\n美容院 \n海狸 \n床\n床单\n床架\n卧室 \n床上用品 \n便盆 \n卧室窗户 \n床头灯 \n蜜蜂 \n山毛榉\n牛肉 \n养蜂人 \n蜂鸣器 \n啤酒 \n啤酒瓶 \n啤酒罐 \n啤酒花园 \n啤酒杯 \n啤酒馆\n甜菜 \n甲虫 \n米色 \n时钟 \n甜椒 \n钟楼 \n皮带\n皮带扣 \n长凳\n弯曲 \n孟加拉虎 \n盒饭 \n贝雷帽 \n浆果 \n停泊位 \n饮料 \n围嘴 \n拌饭 \n圣经 \n比熊\n自行车 \n自行车头盔 \n自行车车轮 \n自行车骑士\n坐浴盆 \n大本钟 \n自行车道 \n自行车道 \n自行车赛\n骑车\n比基尼 \n比基尼上衣\n账单\n台球\n广告牌 \n台球台\n垃圾箱\n活页夹\n双筒望远镜 \n生物学实验室 \n双翼飞机 \n桦木 \n桦树 \n鸟 \n鸟池\n喂鸟器 \n鸟舍\n鸟巢 \n鸟池\n鸟笼 \n出生 \n生日 \n生日蛋糕 \n生日蜡烛 \n生日贺卡 \n生日聚会 \n饼干 \n主教 \n野牛 \n钻头\n咬 \n黑色\n黑山羊\n黑莓 \n乌鸦\n黑板\n铁匠 \n叶片/刀片\n毯子/覆盖层\n运动外套 \n看台\n搅拌机 \n祝福 \n窗帘\n眼罩 \n闪光 \n暴风雪 \n块 \n博客 \n血 \n开花\n花\n女装衬衫\n吹\n吹风机\n河豚 \n蓝色\n蓝色艺术家\n蓝松鸦\n蓝天\n蓝莓 \n蓝知更鸟 \n猪 \n板子\n板擦\n棋盘游戏 \n木板路 \n船 \n船甲板\n船屋\n桨 \n乘船 \n浮标\n山猫 \n躯干\n身体冲浪板\n健美运动员 \n水煮鸡蛋 \n锅炉 \n饰扣式领带\n门闩\n炸弹 \n轰炸机 \n披肩榛鸡\n骨骼\n篝火 \n阀盖 \n盆景 \n书 \n书籍封面\n书柜 \n文件夹 \n书签 \n书架\n书店 \n远程拾音器\n推动\n靴子\n边界\n边境牧羊犬 \n植物园 \n瓶 \n瓶盖 \n开瓶器 \n螺旋开瓶器\n三角梅\n巨石\n花束 \n时装店\n精品酒店 \n鞠躬/蝴蝶结\n领结 \n弓形窗\n碗 \n保龄球运动\n保龄球馆 \n保龄球 \n保龄球设备 \n盒子 \n箱形梁桥\n箱龟 \n拳击手 \n内裤 \n拳击 \n拳击手套 \n拳击台\n男孩 \n支撑物\n支架 \n辫子\n大脑 \n刹车 \n刹车灯 \n树枝\n商标\n白兰地 \n黄铜 \n黄铜牌匾 \n面包 \n面包箱 \n休息\n早餐 \n防浪堤 \n胸部\n啤酒厂 \n砖块\n砖建筑物\n墙 \n砖块\n婚纱 \n新娘 \n新郎 \n伴娘 \n桥 \n缰绳 \n公文包 \n明亮的 \n边沿\n钻头\n广播 \n西兰花 \n青铜 \n铜牌 \n青铜雕塑 \n青铜雕像 \n胸针 \n小溪\n扫帚 \n肉汤 \n棕色\n棕熊 \n巧克力蛋糕 \n早午餐 \n浅黑肤色的女人 \n刷子\n郊狼\n包菜\n气泡\n泡泡糖 \n珍珠奶茶\n斗柜 \n盾牌\n芽 \n佛 \n水牛 \n自助餐 \n昆虫\n建造\n建造者\n建筑 \n积木\n建筑立面 \n建筑材料 \n灯 \n牛 \n斗牛犬 \n子弹 \n动车 \n公告栏 \n防弹背心 \n斗牛 \n扩音器 \n斗牛场 \n大黄蜂 \n保险杠 \n卷/地形起伏\n捆\n蹦极 \n双层床 \n地堡/击球\n兔子 \n浮标 \n书桌\n墓室 \n燃烧 \n玉米煎饼 \n公交车\n公交车司机\n公交车内部\n公交车站 \n公交车站 \n公交车窗户\n灌木\n商业\n名片 \n业务主管 \n商务西装\n业务团队 \n女商人\n商人 \n半身像\n屠夫 \n肉铺\n孤峰 \n黄油 \n奶油 \n蝴蝶 \n蝴蝶馆\n按钮 \n梧桐树\n购买\n出租车 \n小屋 \n卷心菜 \n小屋/机舱\n守车\n储藏柜\n橱柜\n电缆 \n缆车 \n仙人掌 \n咖啡馆 \n食堂 \n笼子\n蛋糕 \n蛋糕台\n计算器 \n大锅 \n日历 \n小腿 \n通话\n电话亭\n书法 \n平静的\n摄像机 \n骆驼 \n相机 \n相机镜头 \n迷彩\n露营\n露营者 \n篝火 \n露营\n营地 \n校园 \n罐\n开罐器 \n运河 \n金丝雀 \n癌症 \n蜡烛 \n烛台 \n糖果 \n块状糖\n柺杖糖 \n糖果店 \n拐杖\n罐子\n大炮 \n树冠/顶棚\n四柱床\n香瓜 \n悬臂桥 \n帆布 \n峡谷 \n帽子\n斗篷\n科德角 \n卡布奇诺\n胶囊 \n队长 \n捕获 \n车 \n汽车经销商 \n车门 \n汽车内饰\n车标\n后视镜\n停车场 \n汽车座椅\n车展\n洗车 \n车窗 \n焦糖 \n卡片\n纸牌游戏\n纸板 \n纸板盒 \n羊毛衫\n红衣凤头鸟\n货物 \n货运飞机 \n货船 \n加勒比 \n康乃馨 \n狂欢节 \n食肉动物 \n旋转木马 \n鲤鱼 \n木匠\n地毯 \n拖鞋 \n红雀\n长途客车\n斑点狗\n航空母舰\n胡萝卜 \n胡萝卜蛋糕 \n携带 \n手推车\n纸箱/纸盒\n卡通 \n卡通人物 \n卡通插图 \n卡通风格 \n雕刻 \n容器\n现金 \n腰果 \n赌场 \n砂锅 \n磁带 \n盒式录音机\n石膏绷带\n铸造 \n城堡 \n猫 \n猫窝\n猫粮 \n猫器具\n猫架\n地下墓穴 \n双体船 \n美洲狮\n握着/抓着\n捕手 \n毛毛虫 \n鲶鱼 \n教堂 \n牛 \n猫步 \n走秀 \n菜花 \n洞穴 \n鱼子酱 \n光盘\nCD播放器\n雪松 \n天花板 \n吊扇 \n庆祝 \n庆典\n名人 \n芹菜 \n大提琴 \n手机 \n水泥 \n墓地 \n中心装饰品\n蜈蚣 \n陶瓷 \n瓷砖 \n麦片 \n仪式 \n证书 \n链条\n链锯 \n椅子 \n升降椅 \n躺椅\n木屋\n圣杯\n粉笔 \n房间\n变色龙 \n香槟酒\n香槟杯\n冠军\n锦标赛\n吊灯\n婴儿换尿布台\n通道\n皴裂处\n小教堂\n人物雕塑\n木炭\n充电\n充电器\n战车\n慈善机构\n慈善活动\n魅力\n图表\n追逐\n底盘\n检查/支票\n支票簿\n棋盘\n检查表\n欢呼声\n鼓励/啦啦队\n奶酪\n奶酪汉堡\n奶酪蛋糕\n猎豹\n厨师\n化合物\n化学家\n化学\n化学实验室\n旗袍\n樱桃\n樱花\n樱桃番茄\n樱桃树\n国际象棋\n栗子\n鸡\n鸡胸肉\n鸡笼\n鸡肉沙拉\n鸡翅\n鹰嘴豆\n小衣橱\n吉娃娃\n孩子\n童星\n孩子的房间\n红番椒\n辣热狗\n烟囱\n黑猩猩\n瓷器\n白菜\n中国园林\n中国结\n月季\n中国塔\n炸薯条/炸薯条\n花栗鼠\n凿子\n巧克力\n巧克力棒\n巧克力蛋糕\n巧克力碎片\n巧克力饼干\n巧克力牛奶\n巧克力慕斯\n松露\n唱诗班\n厨房刀\n砧板\n筷子\n圣诞节\n圣诞球\n圣诞贺卡\n圣诞装饰\n圣诞晚宴\n平安夜\n圣诞帽\n圣诞灯\n圣诞市场\n圣诞装饰\n圣诞树\n菊花\n教堂\n教堂塔\n苹果酒\n雪茄\n雪茄盒\n香烟\n烟盒\n腰带\n电影院\n摄影师\n肉桂\n圆\n电路\n电路板\n马戏团\n水箱\n柑橘类水果\n城市\n城市公交\n市政厅\n城市夜景\n城市公园\n城市天际线\n城市广场\n城市街道\n城墙\n城市景观\n蛤蜊\n单簧管\n扣子\n班级\n经典\n教室\n锁骨\n爪子\n黏土\n陶器\n清洁\n洁净室\n清洁工人\n清洁用品\n清晰的\n栓\n克莱门氏小柑橘\n客户端\n悬崖\n爬\n爬山\n登山者\n诊所\n夹子\n剪贴画\n剪贴板\n快速帆船\n君子兰\n斗篷\n木底鞋\n特写\n壁橱\n布\n穿衣\n衣服\n晒衣夹\n晒衣绳\n服装店\n云\n云雾森林\n多云\n三叶草\n小丑\n小丑鱼\n俱乐部\n离合器\n手拿包\n煤炭\n海岸\n外套\n衣帽架\n玉米\n公鸡\n凤头鹦鹉\n可卡犬\n驾驶\n蟑螂\n鸡尾酒\n小礼服\n鸡尾酒调制器\n鸡尾酒桌\n可可\n椰子\n椰子树\n咖啡\n咖啡豆\n咖啡杯\n咖啡机\n咖啡店\n咖啡壶\n棺材\n法国白兰地\n螺旋\n硬币\n可口可乐\n滤器\n冷的\n卷心菜沙拉\n合作\n拼贴画\n收藏品\n大学生\n牧羊犬\n碰撞\n颜色\n涂色书\n染色材料\n矮种马\n柱子\n梳子\n密码锁\n喜剧演员\n喜剧\n喜剧电影\n彗星\n舒服\n安慰食物\n漫画书\n漫画人物\n连环画\n指挥官\n评论员\n社区\n通勤\n公司\n指南针\n比赛\n比赛\n竞争者\n作曲家\n作文\n堆肥\n电脑\n电脑机箱\n电脑椅\n电脑桌\n键盘\n计算机显示器\n计算机房\n电脑屏幕\n机箱\n概念车\n音乐会\n音乐厅\n贝壳\n混凝土\n调味品\n避孕套\n独立产权的公寓\n指挥\n锥形物\n会议\n会议中心\n会议厅\n会议室\n五彩纸屑\n冲突\n合流\n连接\n连接器\n温室\n星座\n建筑工地\n建筑工人\n包含\n容器\n集装箱船\n大陆\n轮廓\n合同\n控制\n控制塔\n便利店\n集会\n交谈\n转换器\n可转换的\n输送机\n厨师/烹饪\n烹饪\n烹饪喷雾剂\n炊具\n凉的\n冷却器\n铜\n一本/一册\n珊瑚\n珊瑚礁\n粗绳\n有线电话\n酒\n威尔士矮脚狗\n瓶塞\n软木板\n鸬鹚\n玉米\n玉米田\n玉米面包\n角落\n小号\n飞檐\n燕麦片\n围栏\n走廊\n紧身衣\n化妆品\n化妆刷\n化妆镜\n角色扮演\n服装\n服装电影设计师\n婴儿床\n小屋\n棉花\n棉花糖\n沙发\n倒计时\n柜台\n台面\n最佳乡村歌手\n乡村别墅\n乡村公路\n乡村流行歌手\n农村\n双门小轿车\n夫妇/两人/几个\n情侣写真\n小胡瓜\n课程\n球场\n法院\n院子\n堂兄弟\n工作服\n奶牛\n母牛的颈铃\n牛仔\n牛仔靴\n牛仔帽\n螃蟹\n蟹肉\n裂纹\n摇篮\n工艺\n工匠\n蔓越莓\n起重机\n黑纱\n厕所\n板条箱\n火山口湖\n龙虾\n蜡笔\n奶油乳酪\n奶油罐\n创建\n生物\n信用卡\n新月形\n新月形面包\n山顶\n全体船员\n蟋蟀\n板球用球\n板球队\n板球队员\n钩边\n克罗克电锅\n鳄鱼\n庄稼\n露脐上衣\n交叉\n横木\n十字路口\n相声\n人行横道\n油煎面包块\n乌鸦\n撬棍\n人群\n拥挤的\n皇冠\n阴极射线管屏幕\n耶稣受难像\n巡游\n游轮\n巡洋艇\n面包屑\n压坏\n拐杖\n水晶\n幼兽\n立方体\n黄瓜\n球杆\n袖口\n袖扣\n烹饪\n农田\n杯子\n纸杯蛋糕\n丘比特\n马路牙子\n旋度\n卷发器\n无籽葡萄干\n货币\n咖喱\n窗帘\n曲线\n软垫\n顾客\n切\n餐具\n自行车\n骑自行车\n龙卷风\n汽缸\n铙钹\n柏树\n柏树\n达克斯猎狗\n水仙花\n匕首\n大丽花\n萝卜\n乳制品\n雏菊\n大坝\n损害\n潮湿的\n跳舞\n舞池\n舞蹈室\n舞者\n蒲公英\n黑暗\n黑暗\n飞镖\n圆靶\n指示板\n日期\n女儿\n黎明\n天床上\n日光\n门栓\n死亡\n辩论\n碎片\n玻璃水瓶\n甲板\n双层巴士\n装饰\n装修/装饰\n装饰画\n鹿\n后卫\n神\n熟食\n投递\n拆迁\n怪兽\n演示\n兽窝/休闲室\n牛仔夹克\n牙医\n百货商店\n抑郁症\n德比\n皮肤病\n沙漠\n沙漠公路\n设计\n设计师\n桌子/表格\n台灯\n桌面\n台式电脑\n甜点\n破坏\n侦探\n洗涤剂\n露水\n仪表盘\n钻石\n尿布\n尿布包\n杂志\n死\n饮食\n挖掘机\n数字\n数字时钟\n莳萝\n晚餐\n小船\n餐厅\n晚宴\n餐桌\n恐龙\n浸\n文凭\n指引\n导演\n尘埃\n越野摩托车\n泥土地\n泥土路\n泥路/土路\n灾难\n信徒\n迪斯科舞厅\n迪斯科灯秋\n迪斯科舞厅\n疾病\n盘子\n碟形天线\n洗碗机\n抹布\n菜肴\n洗碗液\n迪斯尼乐园\n自动售货机\n展示\n陈列窗\n壕沟\n潜水\n潜水员\n跳水板\n纸杯\n流行音乐播音员\n杜宾犬\n码头\n医生\n文件\n纪录片\n狗\n狗窝\n犬种\n狗项圈\n狗粮\n狗窝\n洋娃娃\n美元\n玩偶之家\n洋娃娃\n海豚\n穹顶\n住宅\n多米诺骨牌\n驴\n甜甜圈\n涂鸦\n门\n门把手\n受气包\n门牌\n门口\n宿舍\n面团\n市中心\n推土机\n拖\n龙\n蜻蜓\n排水沟\n剧本\n戏剧电影\n画\n抽屉里\n图画/画画\n图钉\n辫子\n连衣裙/特定场合的服装\n礼帽\n正装衬衫\n皮鞋\n大礼服\n梳妆台\n更衣室\n运球\n漂移\n浮木\n钻\n饮品/喝\n饮用水\n开车\n司机\n车道\n无人机\n水滴/下降\n吊灯\n滴管\n干旱\n药物\n药店\n鼓\n鼓手\n鸡腿\n干的\n公爵夫人\n鸭子\n鸭嘴兽\n小鸭子\n布基胶带\n伙计\n二重唱\n粗呢\n独木舟\n哑铃\n饺子\n沙丘\n扣篮\n榴莲\n黄昏\n灰尘\n垃圾车\n簸箕\n羽绒被\nDVD\n染料\n鹰\n耳朵\n御寒耳罩\n耳机\n耳塞\n耳环\n地震\n画架\n复活节\n复活节兔子\n复活节彩蛋\n吃\n餐厅\n泡芙\n日食\n生态系统\n编辑\n教育\n教育家\n鳗鱼\n蛋\n蛋卷\n蛋挞\n打蛋器\n白鹭\n埃菲尔铁塔\n橡皮筋\n上级\n电椅\n电钻\n电工\n电\n电子\n电子器件\n大象\n高度图\n电梯\n电梯轿厢\n电梯门\n电梯大堂\n电梯井\n路堤\n大使馆\n装饰\n灰烬\n会徽\n刺绣\n翡翠\n紧急\n紧急服务\n紧急车辆\n情感\n帝国大厦\n搪瓷\n外壳/围墙\n茶几\n能源\n订婚\n订婚戒指\n引擎\n机舱\n工程师\n工程\n英国短毛猫\n乐团\n回车键\n演艺人员\n娱乐\n娱乐中心\n入口\n入口大厅\n信封\n马术\n设备\n橡皮擦\n二胡\n侵蚀\n自动扶梯\n食用蜗牛\n浓缩咖啡\n房地产\n河口\n桉树\n晚上\n晚礼服\n夜光\n傍晚天空\n晚上的太阳\n事件\n常绿的\n母羊\n挖掘\n运动\n排气罩\n展览\n出口\n探险者\n爆炸\n延长线\n灭火器\n排气扇\n挤压\n眼睛\n眼影\n眉\n眼线笔\n布料\n纺织品商店\n外观\n脸\n脸部特写\n蜜粉\n毛巾\n面巾纸架\n设施\n工厂\n工厂车间\n集市\n露天市场\n仙女\n猎鹰\n秋天\n家庭\n家庭轿车\n全家福\n家庭房\n风扇/扇子\n尖牙\n农场\n农民\n农民市场\n农舍\n时尚\n时尚配饰\n时装设计师\n时尚的女孩\n时装插图\n时装大片\n时装模特\n时装表演\n快餐\n西式快餐\n父亲\n水龙头\n故障\n动物\n小鹿\n传真\n宴会\n羽毛\n软呢帽\n饲料\n一餐\n饲养\n喂养的椅子\n猫科\n美洲狮\n栅栏\n芬达\n蕨类植物\n雪貂\n摩天轮\n渡船\n肥料\n节日\n纤维\n小说\n小说书\n田野/场地/野外\n田间道路\n无花果\n打架\n花样滑冰运动员\n小雕像\n文件\n档案照片\n文件柜\n填满\n胶片相机\n电影导演\n电影格式\n电影首映礼\n电影制片人\n拍摄\n过滤器\n鳍\n手\n终点线\n冷杉\n冷杉树\n火\n火灾报警\n消防部门\n消防车\n消防通道\n消防水带\n火坑\n消防站\n爆竹\n消防队员\n壁炉\n烟花\n烟花表演\n急救箱\n鱼\n鱼船\n海鲜市场\n鱼塘\n鱼缸\n渔夫\n钓鱼\n渔船\n渔网\n钓鱼\n渔村\n健身\n健身课程\n五个\n固定装置\n峡湾\n国旗\n旗杆\n小薄片\n火焰\n火烈鸟\n法兰绒\n拍打\n耀斑\n闪光\n烧瓶\n平\n比目鱼\n风味\n跳蚤\n跳蚤市场\n舰队\n飞行\n空中乘务员\n翻转\n触发器\n翻转图\n浮动\n群\n洪水\n地板/地面\n落地扇\n脚垫\n楼层平面图\n落地窗\n插花艺术\n花店\n牙线\n面粉\n流动\n花\n花篮\n花坛\n花箱\n花田\n花童\n花卉市场\n流体\n冲洗\n长笛\n飞\n飞行钓鱼\n传单\n马\n泡沫\n雾\n多雾的\n鹅肝酱\n箔纸\n折椅\n树叶\n民间艺术家\n民间舞蹈\n民间摇滚艺术家\n方旦糖\n火锅\n圣洗池\n食物\n食用色素\n美食广场\n食品加工机\n小吃摊\n快餐车\n桌上足球\n脚\n人行桥\n足球\n足球教练\n大学橄榄球赛\n足球比赛\n足球场\n足球比赛\n橄榄球头盔\n足球运动员\n足球场\n足球队\n小路\n脚印\n脚踏板\n台座\n鞋子\n故宫\n浅滩\n额头 \n森林 \n森林大火 \n森林地面 \n森林小路\n森林公路\n锻造\n餐叉\n叉车 \n表格\n园林\n队列/形成物\nF1方程式赛车\n堡垒\n碉堡\n追逐\n化石\n粉底\n喷泉\n钢笔\n狐狸 \n框架 \n雀斑 \n高速公路 \n卡车 \n法国\n法国斗牛犬 \n薯条 \n法式吐司 \n化妆水\n冰箱 \n炸鸡 \n煎蛋 \n炒饭 \n友谊\n飞盘 \n青蛙 \n霜 \n结霜 \n严寒\n结冰\n水果 \n水果蛋糕 \n水果盘 \n水果市场 \n水果沙拉 \n水果摊\n果树 \n水果商店 \n油炸食品\n煎锅 \n软糖\n燃料 \n吸烟罩\n有趣的 \n葬礼 \n真菌 \n漏斗 \n毛皮衣服\n毛皮大衣 \n家具 \n蒲团 \n小工具 \n枪口\n星云/星系\n美术馆\n游戏 \n游戏棋盘\n游戏手柄\n火腿 \n团伙\n车库 \n车库门 \n手工模型\n垃圾 \n花园 \n花园芦笋 \n橡胶软管 \n花园蜘蛛\n园丁 \n园艺 \n加菲猫\n滴水嘴 \n花环 \n大蒜 \n衣服\n气体 \n加油站 \n煤气炉 \n防毒面具\n收集 \n聚集\n测量仪器\n露台 \n齿轮 \n壁虎 \n艺妓\n凝胶 \n百货商店 \n发电机 \n天竺葵 \n幽灵\n礼物 \n礼品袋 \n礼品篮 \n礼物盒 \n礼品卡 \n礼品商店 \n礼物包装 \n演唱会\n杜松子酒\n姜 \n姜饼 \n姜饼屋 \n银杏树 \n长颈鹿 \n女孩 \n给 \n冰川 \n角斗士\n玻璃珠 \n玻璃瓶 \n玻璃碗 \n玻璃箱\n玻璃建筑 \n玻璃门 \n玻璃地板 \n玻璃屋\n玻璃罐 \n玻璃板 \n玻璃桌子 \n玻璃花瓶 \n玻璃墙\n玻璃窗 \n眼镜 \n光滑面\n滑翔机 \n地球 \n手套 \n发光 \n汤圆 \n去 \n袭击\n球门\n守门员 \n山羊 \n羊奶酪\n戈壁 \n护目镜/墨镜\n黄金 \n金牌 \n金门大桥 \n金毛猎犬 \n金鱼 \n高尔夫运动\n高尔夫球帽 \n高尔夫球车 \n高尔夫球杆\n高尔夫球场 \n高尔夫球手 \n鹅 \n大猩猩 \n哥特式\n葫芦 \n政府 \n政府机构 \n礼服\n毕业生\n毕业典礼\n谷物\n逆戟鲸 \n大奖赛 \n祖父 \n祖母 \n祖父母 \n花岗岩 \n格兰诺拉麦片 \n葡萄 \n西柚\n葡萄酒\n草 \n蚱蜢 \n草原 \n长满草的 \n擦菜器\n坟墓 \n碎石\n墓碑 \n肉汁 \n调味汁瓶\n灰色\n吃草 \n放牧 \n绿色 \n绿色植物 \n欢迎\n问候 \n贺卡 \n灰狗 \n网格 \n筛子\n烧烤架\n格栅 \n烤鳗鱼 \n磨 \n研磨机\n粗燕麦粉 \n杂货袋\n洞穴\n地松鼠 \n群体\n合影 \n小树林\n生长\n牛油果酱\n警卫 \n看门狗 \n宾馆 \n客房 \n指南 \n豚鼠 \n吉他 \n吉他手 \n海湾 \n海鸥 \n枪 \n高达\n谒师所\n古筝 \n健身房 \n体操运动员 \n栖息地 \n黑客 \n冰雹 \n头发 \n头发颜色 \n发胶 \n毛刷 \n发型 \n发夹 \n发网 \n发夹 \n发型 \n一半 \n礼堂\n万圣节 \n万圣节服装 \n万圣节南瓜 \n露背装 \n汉堡 \n汉堡包\n哈密瓜 \n锤子\n吊床 \n阻碍 \n仓鼠 \n烘手机\n放大镜\n擦手巾 \n手提包 \n手球 \n手铐\n手枪 \n手帕 \n把手\n手锯 \n握手 \n倒立 \n手写\n汉服 \n悬挂\n飞机库\n衣架\n幸福 \n海港\n斑海豹\n硬摇滚艺术家 \n精装书 \n建筑工人\n硬件 \n五金店 \n硬木 \n硬木地板 \n口琴 \n管风琴 \n羽管键琴\n收获 \n收割机 \n坐垫/搁脚凳/草丛\n帽子 \n帽盒 \n双簧管\n山楂 \n干草 \n干草地\n榛子\n头 \n主教练 \n大灯\n床头板 \n头饰 \n海岬 \n总部 \n听力 \n心脏\n心形\n热能\n加热器 \n帚石楠\n树篱\n刺猬 \n脚后跟\n直升机 \n直升机机场\n头盔 \n帮助 \n母鸡 \n指甲花 \n药草\n兽群\n寄居蟹 \n英雄 \n苍鹭\n芙蓉花\n芙蓉花 \n隐藏/隐蔽处\n高杠\n高跟鞋 \n高地 \n突出 \n徒步旅行 \n徒步旅行者 \n徒步靴\n登山设备 \n山丘\n丘陵地\n别墅\n山坡\n印度教寺庙 \n铰链 \n臀部 \n嘻哈艺人 \n河马 \n历史学家 \n历史遗迹\n历史 \n曲棍球 \n冰球馆\n曲棍球比赛 \n曲棍球运动员 \n曲棍球棒\n锄头 \n洞 \n假日\n冬青树\n海参 \n家/住宅\n家用电器\n基地 \n家居装饰 \n室内设计 \n内政部\n家庭影院 \n家庭作业 \n鹰嘴豆泥\n蜂蜜 \n蜂窝\n蜜月\n风帽\n连帽衫 \n挂钩/勾住\n跳 \n地平线 \n犀鸟\n长角牛 \n大黄蜂 \n震惊\n恐怖电影 \n马鞍褥\n马车 \n马场 \n骑马\n马背\n马蹄铁\n软管 \n医院 \n医院病床\n病房 \n主持人\n小旅馆\n热 \n热气球 \n热狗 \n辣椒酱 \n温泉 \n旅馆\n酒店大堂 \n酒店房间 \n电炉\n沙漏 \n房子 \n房子外部\n室内植物 \n悬滑板\n吼 \n蜷缩\n拥抱\n呼啦圈\n人\n增湿器\n蜂鸟\n座头鲸 \n打猎\n狩猎小屋 \n障碍\n飓风 \n哈士奇\n小屋 \n鬣狗 \n混合物\n绣球花 \n消火栓 \n水上飞机 \n冰 \n冰袋 \n北极熊 \n冰洞 \n冰淇淋 \n冰淇淋蛋卷\n冰淇淋商店\n冰块 \n浮冰\n冰球运动员 \n冰球队 \n棒棒糖 \n制冰机\n溜冰场 \n冰雕 \n冰架 \n溜冰鞋\n滑冰\n冰山 \n冰柱\n糖衣/酥皮\n图标 \n身份证照片 \n身份证 \n冰屋\n光/灯光/光线\n鬣蜥蜴\n照亮 \n插图\n形象\n黑斑羚\n熏香\n独立日 \n个人\n室内 \n划船器\n电磁炉 \n工业区 \n工业\n步兵 \n充气艇 \n服务台 \n基础设施 \n成分 \n吸入器 \n注射 \n受伤 \n墨水 \n印泥\n小湖湾\n题词\n昆虫\n安装 \n乐器/器械\n绝缘杯 \n互动\n室内设计\n网站 \n十字路口 \n面试 \n无脊椎动物 \n邀请 \n平板电脑\n苹果手机\n苹果音乐播放器\n虹膜 \n铁 \n熨衣板\n灌溉系统 \n岛 \n小岛\n等足类动物\n象牙 \n常青藤\n居酒屋\n千斤顶\n帝王蟹/蟹\n夹克衫\n按摩浴缸\n玉\n美洲虎\n监狱牢房\n果酱\n日式花园\n茉莉花\n下巴 \n松鸦 \n爵士乐 \n爵士乐艺术家\n爵士融合艺术家\n牛仔裤\n吉普车 \n果冻 \n果冻豆\n水母 \n喷气式飞机\n摩托艇 \n珠宝 \n珠宝 \n珠宝店\n拼图游戏\n人力车 \n赛马骑师\n赛马帽\n慢跑 \n联合的\n记者 \n操纵杆 \n法官 \n水壶\n玩杂耍\n果汁\n榨汁器\n枣子\n跳绳\n连身裤 \n丛林\n废品堆放场\n羽衣甘蓝\n万花筒\n袋鼠\n卡拉ok \n空手道 \n卡丁车运动 \n旧城区\n皮船\n烤肉串 \n按键/钥匙\n门卡\n卡其色\n踢\n苏格兰裙\n和服\n幼儿园教室 \n幼儿园 \n国王\n帝王蟹 \n亲吻\n工具包 \n厨房 \n厨房橱柜\n厨房台面\n厨房地板\n厨房抽油烟机\n厨房岛\n厨房水槽\n厨房桌子\n厨房用具\n厨房窗户\n厨房用具\n风筝 \n猕猴桃 \n护膝\n跪下\n餐刀\n骑手\n编织\n编织针\n球形把手\n门环\n结\n考拉 \n锦鲤\nktv\n实验室 \n实验室外套\n标签\n拉布拉多\n迷宫\n网眼织物\n蕾丝连衣裙 \n梯子\n长柄杓\n瓢虫\n环礁湖 \n湖泊\n湖区 \n湖边小屋\n湖岸 \n羊肉 \n羊排 \n灯柱 \n灯罩 \n矛 \n土地\n陆地车辆 \n废物填埋\n着陆\n降落甲板\n地标\n风景\n山崩\n挂带\n灯笼 \n腿/大腿\n笔记本电脑\n笔记本键盘\n幼体\n烤宽面条\n激光\n睫毛\n套索 \n门闩\n乳胶 \n拿铁咖啡 \n笑\n发射\n发布会\n举办会议\n自助洗衣店 \n洗衣房\n洗衣篮 \n洗衣房 \n熔岩 \n薰衣草 \n草坪\n草坪婚礼 \n律师 \n躺 \n引领 \n主唱 \n通向\n领袖 \n泄漏 \n倾斜/倚靠\n学习 \n皮带 \n皮革 \n皮夹克 \n皮鞋 \n演讲 \n演讲厅 \n教学室\n窗台 \n剩饭\n腿 \n传说 \n紧身裤/秋裤\n立法院 \n乐高 \n豆类 \n柠檬 \n柠檬汁 \n柠檬水 \n狐猴 \n镜头 \n眩光 \n扁豆 \n豹 \n紧身连衣裤 \n紧身裤袜\n小妖精 \n课程\n信函\n信箱 \n信的标志 \n刻字 \n生菜 \n水平 \n图书馆 \n许可证 \n车牌 \n地衣 \n舔 \n盖子 \n躺着\n安全带 \n救生衣 \n救生艇 \n救生员 \n提起\n灯具 \n灯光秀 \n电灯开关\n照明/照明设备\n闪电 \n避雷针 \n淡紫色 \n百合\n肢体 \n石灰 \n石灰石 \n豪华轿车 \n线条\n艺术线条\n排队 \n亚麻 \n邮轮\n狮子 \n润唇膏 \n口红 \n液体 \n酒类商店\n列表 \n荔枝 \n生活 \n家畜\n客厅 \n生活空间 \n蜥蜴 \n负载 \n装卸码头\n游手好闲的人 \n走廊\n定位 \n锁 \n闸室 \n储物柜 \n阁楼 \n原木\n小木屋\n标志 \n洛基 \n长头发 \n冲浪板\n隐约显现/织布机\n环状\n遗失\n彩票 \n莲花 \n爱 \n双人沙发\n行李 \n木材 \n伐木工人 \n午餐 \n午餐盒 \n郁郁葱葱的 \n奢侈品 \n豪华游艇 \n雨衣\n澳洲胡桃\n短尾猿 \n通心粉 \n金刚鹦鹉 \n弯刀 \n机器\n机枪 \n杂志 \n魔法 \n魔术师 \n磁铁 \n放大镜 \n木兰花\n喜鹊 \n麻将 \n象夫\n女仆 \n邮件 \n邮件槽 \n制作\n改造 \n化妆师 \n化妆工具 \n野鸭 \n野鸭 \n槌棒\n哺乳动物 \n猛犸象\n男人\n管理 \n经理 \n海牛 \n曼荼罗 \n橘子 \n普通话 \n鬃毛 \n漫画 \n食槽\n芒果 \n山竹果 \n红树林 \n曼哈顿 \n检修孔\n井盖\n修指甲 \n人体模型 \n庄园主宅\n大厦 \n螳螂 \n地幔 \n活动房层\n制造业 \n手稿 \n地图 \n枫木 \n枫叶 \n枫糖浆 \n沙球 \n马拉松 \n大理石 \n行进\n行进乐队\n母马 \n金盏花 \n水兵\n海洋无脊椎动物 \n海洋哺乳动物 \n木偶 \n标志\n集市\n市场广场\n市场摊位 \n结婚\n武术\n武术家 \n武术馆 \n马提尼\n马丁尼酒杯\n睫毛膏\n吉祥物 \n土豆泥 \n搅碎机 \n面具/口罩\n按摩 \n桅杆 \n地垫\n斗牛士 \n比赛\n火柴盒 \n衣料\n床垫 \n陵墓 \n长裙\n一餐\n量杯\n卷尺 \n肉类\n肉丸 \n机械师 \n机械风扇 \n奖牌\n媒体 \n医疗设备 \n医学图像 \n医务人员 \n医药箱 \n中世纪的\n麦地那市\n冥想 \n猫鼬 \n赛事\n香瓜\n纪念碑 \n菜单 \n美人鱼 \n网 \n肮脏\n信使袋 \n金属 \n金属艺术家\n金属探测器 \n计量器\n中层楼\n麦克风 \n显微镜 \n微波炉\n午夜 \n里程碑\n军装 \n牛奶\n牛奶罐\n奶茶 \n奶昔 \n磨坊\n矿井\n矿工\n矿物质\n矿泉水 \n迷你 \n微缩模型\n面包车\n部长 \n小型货车\n薄荷 \n薄荷糖 \n镜子 \n小姐 \n投掷物\n任务 \n槲寄生\n混合 \n搅拌机\n搅拌碗\n混合物 \n护城河 \n电动踏板车\n模型/模特\n汽车模型 \n现代 \n现代大厦 \n潮湿 \n模具 \n模具\n鼹鼠\n君主 \n钱 \n监控器\n和尚 \n猴子 \n活动扳手 \n黑白照片\n独轮脚踏车 \n怪物卡车 \n月亮 \n月饼 \n月光 \n沼泽\n驼鹿 \n拖把\n助力车\n早晨\n晨雾 \n晨光 \n朝阳\n砂浆 \n马赛克\n清真寺 \n蚊子 \n藓类植物\n汽车旅馆 \n蛾 \n母亲\n主板 \n主题 \n动作\n电动机 \n摩托车 \n摩托车 \n摩托车头盔 \n摩托车赛车手 \n骑摩托车的人 \n赛车运动 \n土堆\n山 \n山地自行车 \n山地自行车员\n山地自行车运动\n山地大猩猩 \n山湖 \n山景观 \n山口 \n山路 \n山脉 \n山区河流 \n山雪 \n山间溪流\n山景城 \n山村 \n登山者 \n登山包 \n鼠标/鼠\n鼠标垫 \n捕鼠器 \n嘴\n漱口水 \n移动 \n电影海报 \n电影票 \n割草机 \nmp3播放器 \n先生 \n泥 \n松饼 \n马克杯\n桑树\n覆盖物 \n骡子 \n直辖市 \n壁画 \n肌肉 \n肌肉车 \n博物馆 \n蘑菇 \n音乐 \n音乐节 \n音乐凳子 \n音乐工作室 \n音乐录影带表演者 \n音乐键盘 \n音乐家 \n贻贝 \n芥末 \n神话 \n烤干酪辣味玉米片 \n指甲油 \n指甲锉\n保姆 \n餐巾 \n狭窄的 \n国旗 \n基督诞生的场景 \n自然历史博物馆 \n自然 \n自然保护区 \n导航 \n九夜节\n海军 \n星云 \n脖子 \n围颈带/领口\n项链 \n领口 \n花蜜 \n油桃 \n针状物\n邻居\n与某处邻近的地区\n霓虹灯\n霓虹灯 \n神经 \n巢 \n新年 \n新生的\n纽芬兰 \n新婚 \n新闻 \n记者招待会\n报摊 \n晚上 \n夜市 \n夜空 \n夜景 \n夜总会 \n床头柜\n面条 \n鼻子 \n鼻羁 \n注解\n笔记本 \n记事本 \n信纸 \n公告\n数字图标\n修女 \n护士 \n托儿所 \n养老院 \n螺母 \n胡桃夹子 \n橡木 \n橡树 \n桨 \n绿洲 \n烘干室 \n燕麦片 \n燕麦 \n方尖塔 \n观察塔 \n天文台 \n超越障碍训练场 \n海洋 \n章鱼 \n提供 \n办公室 \n办公大楼 \n办公椅 \n办公室隔间 \n办公桌\n办公用品 \n办公室的窗户 \n军官\n行政官员\n石油 \n油灯 \n油画 \n石油钻台\n秋葵 \n老照片 \n橄榄 \n橄榄油 \n橄榄树 \n煎蛋卷 \n洋葱 \n洋葱圈 \n蛋白石 \n开阔的/张开\n开始\n开幕式 \n歌剧 \n歌剧院 \n操作 \n手术室 \n操作 \n眼镜店 \n猩猩 \n橙子/橙色\n橙汁 \n橙树 \n橘园 \n轨道 \n果园 \n乐池\n兰花 \n订单 \n组织 \n折纸 \n点缀 \n鱼鹰 \n鸵鸟 \n水獭 \n外面的\n露头 \n户外 \n厕所 \n电源插头\n大纲 \n椭圆形 \n烤箱 \n整体 \n大衣 \n天桥 \n猫头鹰 \n牡蛎 \n橡皮环 \n包裹\n包/包装/包裹\n围场 \n警车 \n挂锁 \n肉菜饭 \n宝塔 \n疼痛 \n油漆刷 \n画家 \n佩斯利印花大手帕 \n宫殿\n调色板 \n栅栏\n棺罩\n棕榈树 \n平底锅\n煎饼 \n熊猫 \n面板 \n全景 \n三色堇\n喘息\n储藏室 \n裤子 \n连裤袜 \n木瓜 \n纸 \n纸袋 \n切纸机 \n纸灯笼 \n纸盘子 \n纸巾 \n平装书 \n压纸器 \n降落伞 \n游行 \n天堂 \n鹦鹉 \n护理人员 \n长尾小鹦鹉\n滑翔伞 \n伞兵 \n羊皮纸 \n教区 \n公园 \n公园长椅\n停车 \n停车场 \n停车费 \n停车标志 \n议会 \n欧芹/香菜\n参与者 \n合作伙伴 \n帕特里奇 \n聚会\n派对帽 \n通过 \n通道 \n存折 \n乘客 \n客船 \n旅客列车 \n百香果 \n护照 \n面食\n粘贴 \n糕点 \n牧场 \n补丁 \n病人 \n图案/款式\n人行道/硬路面\n大帐篷\n爪子 \n支付 \n付费电话 \n豌豆 \n和平 \n桃子 \n孔雀 \n山峰/尖顶\n花生 \n花生酱 \n梨 \n珍珠 \n卵石 \n山核桃 \n行人\n人行天桥 \n步行街 \n果皮\n削皮器 \n小钉板 \n木质腿\n鹈鹕 \n笔/围栏\n点球 \n铅笔 \n铅笔盒\n卷笔刀 \n铅笔裙 \n吊坠 \n钟摆\n企鹅 \n半岛 \n锦标旗\n便士\n储蓄罐 \n牡丹 \n胡椒/辣椒\n胡椒研磨机 \n胡椒子\n意大利辣香肠 \n栖息/鲈鱼\n表演\n表演\n表演舞台 \n香水 \n绿廊 \n波斯猫 \n柿子 \n个人护理 \n个人漂浮装置 \n害虫 \n宠物 \n宠物店 \n宠物店 \n花瓣 \n佩妮 \n教堂的长椅\n野鸡 \n现象 \n哲学家 \n电话 \n电话簿 \n留声机 \n照片 \n照相亭 \n相框 \n摄影 \n物理学家 \n物理实验室 \n钢琴家 \n钢琴 \n选择 \n捡起 \n泡菜 \n野餐 \n野餐区 \n野餐篮 \n野餐桌\n图片 \n相框 \n馅饼\n鸽子 \n朝圣者 \n药片\n枕头 \n飞行员 \n领航艇 \n别针\n松树\n松果 \n松林 \n松子 \n菠萝 \n乒乓球桌 \n乒乓球 \n粉色\n一品脱的量 \n琵琶 \n管子\n管碗 \n海盗 \n海盗旗 \n海盗船 \n阿月浑子 \n滑雪场 \n口袋里的面包 \n火龙果 \n斗牛犬 \n球场 \n大水罐\n猪笼草 \n干草叉 \n披萨 \n披萨刀 \n比萨锅 \n披萨店 \n招牌 \n地方 \n餐具垫 \n格子 \n平原 \n示意图\n行星\n行星地球\n厚木板\n植物 \n种植园 \n种植 \n匾额\n石膏 \n塑料 \n橡皮泥 \n高原 \n平台 \n白金\n大浅盘\n玩/演奏/运动\n打羽毛球 \n打棒球 \n打篮球 \n玩台球 \n踢足球 \n玩乒乓球 \n打网球 \n打排球 \n选手/运动员\n操场\n剧场 \n扑克牌 \n下棋 \n打高尔夫球 \n打麻将 \n运动场\n护栏\n游戏室 \n广场 \n钳子 \n故事情节\n犁 \n插头 \n插头帽 \n李子 \n水管工 \n卫生洁具 \n羽毛\n夹板 \n口袋\n怀表 \n随身小折刀 \n圆荚体 \n乐队指挥台\n诗歌 \n一品红 \n指/朝向\n指针 \n扑克卡 \n筹码 \n扑克表 \n杆/柱\n臭猫 \n警察 \n警车 \n警犬 \n警察局 \n政治家 \n圆点 \n花粉 \n污染 \n马球 \n马球领 \n马球衬衫 \n石榴 \n波美拉尼亚的 \n雨披 \n池塘 \n马尾辫 \n贵宾犬 \n池 \n流行 \n流行艺术家 \n爆米花 \n教皇 \n罂粟 \n瓷 \n玄关 \n猪肉 \n粥 \n便携式电池 \n门户网站 \n投资组合 \n汽门 \n肖像 \n肖像会话 \n摆姿势拍照\n负鼠 \n帖子 \n邮局 \n邮票 \n明信片 \n海报 \n海报页 \n锅/罐/陶盆\n土豆 \n土豆片 \n土豆沙拉 \n布垫子 \n便壶\n袋 \n家禽 \n英镑 \n倾泻\n粉末\n电源线\n电源插头及插座 \n权力看 \n电站 \n练习\n布拉格城堡 \n祈祷 \n牧师 \n首映 \n处方 \n显示 \n演讲 \n总统 \n新闻发布室\n高压锅 \n椒盐卷饼 \n王子 \n公主 \n打印 \n打印页面 \n打印机 \n印刷 \n监狱 \n农产品/生产\n产品 \n职业 \n专业的\n教授 \n项目图片 \n投影屏幕 \n投影仪 \n毕业舞会 \n散步 \n螺旋桨 \n先知 \n建议 \n防护服 \n抗议 \n抗议者 \n出版 \n宣传画像\n冰上曲棍球 \n布丁 \n水坑 \n泡芙 \n角嘴海雀 \n哈巴狗 \n拉 \n讲坛 \n脉冲 \n泵 \n南瓜 \n南瓜饼 \n南瓜种子 \n拳击吊袋\n拳头猛击/穿孔\n学生 \n紫色\n推 \n轻轻一击\n谜题 \n塔 \n金字塔 \n大蟒\n二维码 \n鹌鹑 \n采石场 \n季度 \n石英 \n女王 \n油炸玉米粉饼 \n队列 \n乳蛋饼 \n被子 \n绗缝 \n引用\n兔子 \n浣熊 \n比赛 \n赛道 \n水沟/跑道\n赛车 \n球拍 \n雷达 \n散热器 \n广播 \n木筏/橡皮艇\n布娃娃 \n栏杆/铁轨\n轨道车 \n铁道\n铁路桥梁 \n轨道线\n火车站 \n雨 \n雨靴\n彩虹 \n虹鳟鱼 \n雨衣 \n热带雨林 \n多雨的 \n葡萄干 \n耙子\n公羊\n斜坡 \n油菜籽\n快速 \n说唱歌手 \n树莓 \n老鼠 \n棘轮 \n乌鸦 \n峡谷 \n雷 \n剃须刀 \n锋利的 \n阅读\n阅读材料\n钻孔器\n后面\n尾灯 \n后视图\n后视镜 \n收据 \n收到 \n接待 \n配方 \n记录 \n唱片制作人 \n记录器/竖笛\n录音室 \n娱乐室 \n休闲车 \n矩形 \n回收 \n回收站 \n红色\n红地毯 \n红旗 \n红熊猫 \n红酒 \n红木 \n芦苇\n礁石\n卷轴\n裁判 \n倒影\n倒影\n反射器 \n注册 \n控制 \n驯鹿 \n放松 \n释放 \n救援 \n宗教 \n宗教的\n享受 \n保持 \n改造 \n遥控器\n移除\n修复 \n维修店 \n爬行动物 \n救援 \n救助者 \n研究 \n研究员 \n储层 \n住宅 \n居民区 \n树脂 \n度假胜地 \n度假小镇\n餐厅的厨房 \n餐厅的露台 \n厕所 \n零售 \n寻回犬 \n制动火箭\n揭示 \n犀牛 \n杜鹃 \n肋骨 \n丝带 \n大米 \n电饭煲 \n稻田 \n骑/搭乘\n脊 \n骑马\n步枪 \n边缘\n环/戒指\n暴乱\n涟漪 \n上升 \n高层建筑\n河 \n河岸 \n河船 \n河谷 \n河床 \n路 \n路标 \n公路旅行 \n路边 \n烤鸡 \n长袍 \n罗宾 \n机器人 \n石头 \n岩石拱 \n摇滚艺术家 \n摇滚乐队 \n攀岩者 \n攀岩 \n摇滚音乐会 \n岩石表面 \n岩层 \n摇滚歌手 \n火箭 \n摇椅 \n岩石 \n啮齿动物 \n牛仔竞技表演 \n竞技舞台 \n罗伊 \n狍子 \n辊 \n过山车 \n轮式溜冰鞋 \n溜冰鞋 \n擀面杖 \n浪漫 \n浪漫的 \n屋顶 \n屋顶花园 \n房间 \n房间分频器 \n根 \n根啤酒 \n绳索桥 \n念珠 \n玫瑰 \n迷迭香 \n玫瑰色的云 \n罗特韦尔犬 \n圆桌 \n路由器 \n行 \n罗文 \n皇家 \n橡皮图章 \n废墟 \n魔方 \n红宝石\n莱夫 \n橄榄球 \n橄榄球 \n橄榄球运动员 \n毁坏\n尺\n朗姆酒 \n跑\n跑步者 \n跑步鞋 \n农村的\n锈 \n乡村的\n黑麦 \n袋 \n鞍 \n鞍囊\n旅行\n安全 \n安全背心 \n圣人 \n帆 \n帆船 \n航行 \n水手 \n松鼠猴 \n缘故\n沙拉 \n沙拉碗 \n火蜥蜴 \n意大利蒜味腊肠 \n出售 \n三文鱼\n沙龙 \n萨尔萨舞 \n盐 \n盐和胡椒瓶 \n盐湖 \n盐沼 \n盐瓶 \n敬礼 \n萨莫耶德人 \n武士 \n沙子 \n沙洲 \n砂箱 \n沙堡 \n沙雕 \n凉鞋 \n三明治 \n卫生巾 \n圣诞老人 \n蓝宝石 \n沙丁鱼 \n莎丽 \n生鱼片 \n沙爹 \n书包 \n卫星 \n缎 \n酱汁 \n碟子\n桑拿 \n香肠 \n稀树大草原 \n锯\n锯木架\n萨克斯管\n萨克斯手 \n脚手架 \n秤/标尺\n比例模型 \n扇贝 \n疤痕 \n稻草人 \n围巾 \n场景 \n风景 \n雪纳瑞犬 \n学校 \n校车 \n校服 \n校舍 \n纵帆船\n科学 \n科幻电影 \n科学博物馆 \n科学家 \n剪刀 \n壁灯 \n司康饼 \n勺子\n踏板车/摩托车\n分数 \n记分板 \n蝎子 \n童子军 \n炒蛋 \n废弃\n刮板 \n刮伤 \n屏幕 \n纱门 \n截图 \n螺杆 \n螺丝刀 \n长卷纸/卷轴\n擦洗 \n硬毛刷 \n雕塑家 \n雕塑 \n海洞穴 \n海冰 \n海狮 \n海龟 \n海胆 \n尖吻鲈 \n海底 \n海鸟 \n海鲜 \n海马 \n海豹\n海景 \n海贝 \n海滨度假胜地 \n季节 \n座位 \n安全带 \n海藻 \n秘书 \n安全 \n小轿车 \n看到 \n种子 \n跷跷板 \n赛格威 \n自拍\n出售 \n研讨会 \n感觉 \n传感器 \n服务器 \n服务器机房 \n服务 \n集 \n缝纫机 \n影子 \n摇 \n瓶 \n洗发水 \n形状 \n分享 \n鲨鱼 \n卷笔刀 \n记号笔\n剃须刀 \n剃须膏 \n披肩/围巾\n剪切 \n剪刀\n羊 \n床单 \n乐谱 \n架子\n贝壳\n贝类 \n避难所 \n搁置 \n牧羊人 \n果子露\n柴犬 \n发光 \n航运 \n集装箱 \n海难 \n船厂 \n衬衫 \n赤膊的\n浅滩\n鞋 \n鞋盒 \n鞋店 \n鞋楦 \n射击\n得分篮球后卫 \n商店橱窗 \n门面 \n购物者 \n购物 \n购物袋 \n购物篮 \n购物车 \n购物中心 \n购物街 \n海岸 \n海岸线 \n短的\n短发 \n短裤 \n小酒杯\n散弹枪 \n肩膀 \n单肩包\n铲 \n陈列柜\n淋浴 \n浴帽\n浴帘 \n淋浴门 \n淋浴头 \n碎纸机 \n泼妇 \n虾 \n神社 \n灌木 \n快门 \n暹罗猫\n西伯利亚 \n兄弟姐妹\n侧面\n边柜 \n配菜 \n边车\n边线\n壁板\n标志 \n指示牌\n信号 \n签名 \n丝绸 \n丝袜 \n筒仓 \n银 \n银牌 \n银器 \n唱歌\n烧焦 \n歌手 \n水槽 \n啜\n坐/放置/坐落\n坐着 \n滑板公园\n滑板 \n滑板者 \n溜冰者 \n溜冰场 \n骨架 \n草图 \n串串\n滑雪 \n滑雪靴 \n滑雪设备 \n滑雪服\n滑雪缆车 \n滑雪杖 \n滑雪胜地 \n滑雪板\n滑雪 \n滑雪鞋 \n皮肤 \n头骨 \n无边便帽 \n天空 \n天空塔 \n天窗 \n天际线 \n摩天大楼 \n激流回旋 \n石板\n雪橇 \n睡眠 \n睡袋 \n睡衣\n袖子\n片 \n滑动\n滑块 \n吊索 \n坡 \n投币口\n老虎机 \n树懒\n慢炖锅 \n鼻涕虫 \n贫民窟 \n气味 \n微笑 \n烟雾/抽烟\n零食 \n蜗牛 \n蛇 \n鲷鱼 \n快照 \n通气管 \n鼻子 \n雪 \n雪豹 \n雪山 \n雪球 \n单板滑雪者\n雪原 \n雪花 \n雪人 \n雪地摩托\n雪犁\n雪鞋 \n雪 \n肥皂 \n肥皂泡 \n给皂器 \n足球守门员 \n社会名流\n短袜\n插座\n苏打水 \n垒球 \n软件 \n太阳能电池阵列 \n士兵 \n独奏 \n解决方案 \n宽边帽 \n歌曲\n声音 \n汤 \n汤碗\n汤匙 \n酸奶油 \n纪念品 \n豆浆 \n水疗中心 \n空间 \n航天飞机 \n空间站 \n宇宙飞船 \n意大利面 \n横跨\n扳手 \n火花 \n闪耀 \n烟火\n起泡葡萄酒 \n麻雀 \n抹刀 \n扬声器\n观众 \n会话框\n速度限制 \n限速标志 \n快艇 \n车速表\n球 \n香料 \n调料架\n蜘蛛 \n蜘蛛网 \n扣球\n旋转\n菠菜 \n尖塔 \n飞溅 \n海绵 \n勺子 \n体育协会 \n运动器材\n运动团队\n体育球 \n体育器材\n运动会 \n运动服装 \n点 \n喷雾 \n伸展\n春天 \n春卷 \n撒\n洒水器\n发芽 \n云杉 \n云杉森林 \n队 \n广场 \n南瓜 \n蹲 \n挤\n鱿鱼 \n松鼠 \n水枪 \n刺 \n稳定的 \n（码放整齐的）一叠\n体育场 \n工作人员 \n舞台\n舞台灯 \n驿马车\n弄脏\n不锈钢 \n楼梯 \n楼梯 \n楼梯间\n摊位/小隔间\n种马 \n站/矗立/摊位\n站 \n主食 \n订书机 \n星星\n盯着\n海星 \n杨桃 \n燕八哥 \n州立公园 \n公立学校 \n车站\n固定自行车\n文具 \n雕像 \n牛排 \n牛排刀 \n蒸汽 \n蒸汽机 \n蒸汽机车 \n蒸汽火车 \n馒头 \n钢 \n方向盘 \n（花草的）茎\n模版\n梯凳\n立体声 \n听诊器 \n炖\n戳/条状物\n竹节虫 \n贴纸 \n静物画 \n高跷 \n黄貂鱼 \n搅拌 \n搅拌器 \n镫\n缝 \n股票 \n长筒袜\n腹部\n石头建筑 \n石雕 \n石屋\n石磨 \n凳子 \n停止 \n停在 \n红灯 \n停车标志 \n秒表 \n红绿灯 \n存储箱 \n储藏室 \n罐/蓄水池\n商店 \n店面 \n鹳 \n风暴 \n暴风云 \n狂风暴雨的 \n炉子 \n扑克 \n跨骑\n过滤器 \n海峡 \n带 \n稻草/吸管\n草帽 \n草莓 \n溪流\n街头艺术 \n街头艺术家 \n街角 \n流浪狗\n街头食品 \n路灯 \n街市场 \n街头摄影 \n街景 \n路标 \n街头小贩 \n拉伸 \n担架 \n罢工 \n前锋\n细绳\n芝士条\n带子\n条纹 \n漫步 \n结构 \n工作室 \n影棚拍摄 \n材料\n填充玩具动物\n毛绒玩具\n馅\n树桩 \n惊人的 \n特技 \n佛塔 \n风格 \n手写笔\n潜艇 \n潜艇形大三明治\n海底水\n郊区 \n地铁 \n地铁站 \n低音炮 \n多肉\n绒面革\n糖 \n糖碗 \n甘蔗 \n方糖 \n西装\n套房\n夏天 \n夏天傍晚\n峰顶\n太阳 \n太阳帽\n日光浴 \n周日 \n日晷 \n向日葵 \n向日葵田 \n葵花籽\n太阳镜 \n晴天\n日出 \n日落 \n遮阳伞 \n阳光 \n超级碗 \n跑车 \n超级英雄 \n超市 \n超市货架\n超模\n支持者 \n冲浪\n表面 \n冲浪板 \n冲浪者 \n外科医生 \n外科手术\n环绕\n寿司 \n寿司吧 \n背带裤 \n悬架 \n吊桥 \n越野车\n燕子\n燕尾蝶 \n沼泽 \n天鹅 \n天鹅游艇 \n运动裤\n防汗带 \n毛衣 \n运动衫 \n甜的\n红薯 \n游泳 \n泳帽 \n游泳者\n游泳洞 \n游泳池 \n摆动\n平转桥 \n秋千\n漩涡 \n开关 \n转椅 \n剑 \n旗鱼\n象征 \n对称 \n犹太教堂\n注射器 \n糖浆 \n系统 \nt恤 \nt恤 \n塔巴斯科辣椒酱\n虎斑\n乒乓球拍 \n桌面 \n桌布 \n平板电脑 \n餐具 \n转速表 \n拦截\n墨西哥煎玉米卷 \n跆拳道 \n太极 \n尾巴 \n裁缝 \n拍/拿\n起飞 \n说话/交谈/演讲\n手鼓 \n棕褐色 \n橘子 \n胶带/磁带/终点线\n挂毯 \n沥青碎石路面\n芋头 \n篷布\n果馅饼\n流苏 \n味道 \n榻榻米 \n纹身 \n纹身艺术家 \n酒馆 \n茶 \n茶包\n茶话会\n茶园 \n茶壶 \n茶具 \n教 \n老师 \n茶杯 \n水鸭\n团队合影\n团队介绍 \n眼泪/撕裂/划破\n技术员 \n技术 \n泰迪熊\nT字形物\n青少年 \n电线杆 \n变焦镜头 \n望远镜 \n电视 \n电视摄像机 \n电视室\n电视演播室 \n温度 \n寺庙 \n天妇罗 \n网球 \n网球场 \n网球比赛 \n网球网 \n网球运动员 \n网球拍 \n帐篷 \n龙舌兰酒 \n终端/航站楼\n阳台 \n地形 \n玻璃容器 \n领土 \n测试 \n测试赛 \n试管\n文本 \n短信 \n纺织 \n纹理 \n感恩节 \n感恩节晚餐 \n剧院 \n戏剧演员\n治疗 \n温度计 \n热水瓶 \n暖瓶\n恒温器 \n灌木丛 \n顶针 \n东西\n思考 \n蓟 \n宝座 \n金銮殿\n扔 \n抱枕 \n雷\n雷雨 \n百里香 \n皇冠\n记号\n票 \n售票亭 \n潮池 \n领带 \n老虎 \n紧 \n瓦\n瓷砖地板 \n瓦屋顶 \n瓷砖墙 \n锡 \n锡纸 \n箔\n提拉米苏 \n轮胎 \n纸巾\n烤面包 \n烤面包机 \n烟草 \n烟斗 \n学步的小孩\n脚趾 \n豆腐 \n马桶 \n马桶座圈 \n化妆包\n东京铁塔\n番茄 \n番茄酱 \n番茄汤 \n墓 \n钳子\n钳子\n工具 \n工具箱 \n牙刷 \n牙膏 \n牙签 \n修剪成形的花园 \n配料\n火炬/光源\n龙卷风 \n玉米粉圆饼 \n乌龟 \n大手提袋 \n图腾柱 \n龙猫 \n巨嘴鸟 \n触摸 \n触地\n旅行\n旅游巴士 \n导游 \n游客\n旅游景点 \n锦标赛\n拖车\n毛巾 \n毛巾杆 \n大厦 \n塔桥 \n小镇 \n城镇广场\n玩具 \n玩具车 \n玩具枪 \n玩具店 \n跑道\n拖拉机 \n贸易 \n传统 \n传统的 \n交通 \n锥形交通路标 \n交通拥堵 \n交通堵塞 \n交通标志 \n小道 \n预告片 \n拖车 \n火车 \n火车桥 \n火车车厢 \n火车内部 \n火车轨道 \n火车窗口 \n教练 \n训练\n训练长椅\n训练场\n电车/手推车\n蹦床 \n变形金刚\n透明度 \n旅行 \n托盘/碟子\n跑步机 \n美食\n树 \n树枝 \n林场 \n树蛙 \n树屋 \n树根\n树干 \n试验 \n三角形 \n铁人三项\n部落 \n支流 \n戏法/特技\n三轮车 \n修剪 \n三人组 \n三脚架 \n长号 \n部队 \n奖杯\n奖杯 \n热带 \n鳟鱼 \n卡车 \n卡车司机 \n浴缸 \n管子\n拖船 \n郁金香 \n金枪鱼 \n苔原 \n隧道 \n涡轮 \n火鸡 \n转动\n芜菁\n绿松石 \n炮塔 \n乌龟 \n獠牙\n电视演员 \n电视柜 \n电视剧 \n电视节目类型 \n电视名人 \n电视节目 \n情景喜剧 \n电视塔 \n枝条\n黄昏\n双胞胎\n麻线\n扭 \n类型 \n键入\n打字机 \n尤克里里\n奥特曼 \n伞 \n内衣 \n水下 \n独角兽 \n制服\n宇宙 \n大学 \n向上\n城市 \n尿壶 \n瓮\n使用 \n用具 \n杂物间 \n吸尘器/真空\n谷 \n阀门\n吸血鬼\n货车\n香草 \n虚荣 \n种类\n花瓶/瓶\n金库\n矢量卡通插图 \n矢量图标 \n蔬菜\n菜园\n蔬菜市场 \n植被 \n车辆 \n面纱 \n静脉 \n天鹅绒 \n自动售货机 \n小贩\n通风孔\n胡蜂属 \n船 \n背心 \n兽医 \n经验丰富的 \n兽医办公室 \n高架桥 \n视频 \n摄像机 \n电子游戏\n录像带 \n视镜 \n守夜 \n别墅 \n村庄\n藤蔓\n醋 \n葡萄园 \n暴力 \n紫罗兰色\n小提琴 \n小提琴家 \n中提琴演奏者 \n愿景 \n遮阳板 \n伏特加 \n火山 \n排球 \n排球场 \n排球运动员 \n志愿者 \n航行 \n秃鹰 \n华夫饼干\n华夫饼机\n货车\n马车车轮 \n腰 \n服务员 \n候机室 \n等候室 \n走 \n步行\n手杖 \n挂钟 \n壁纸 \n核桃\n海象 \n战争 \n仓库 \n温暖的 \n警告标志 \n战士 \n军舰 \n疣猪 \n洗 \n洗衣机/垫圈\n洗 \n洗衣机 \n黄蜂 \n浪费 \n废物容器 \n手表\n水 \n水鸟 \n水牛 \n水冷却器 \n水滴 \n水景\n热水器 \n水位 \n荷花\n水上乐园\n水管 \n净水器 \n滑水板\n水上运动 \n水面\n水塔 \n水彩 \n水彩插图 \n水彩画 \n瀑布 \n喷壶 \n水印叠加图章\n西瓜 \n防水外套\n水路\n波浪\n蜡 \n武器 \n穿着\n天气 \n叶片 \n网\n摄像头\n婚礼 \n结婚戒指 \n婚礼花束 \n结婚蛋糕 \n新婚夫妇\n婚礼请柬\n婚礼派对\n婚纱照 \n婚礼摄影师 \n婚纱摄影 \n婚宴 \n楔 \n杂草 \n重量 \n体重秤 \n焊接工\n井\n西餐 \n西餐厅 \n湿\n吧台\n潜水衣\n湿地\n潜水服 \n鲸鱼 \n鲸鲨 \n小麦 \n麦田 \n车轮\n轮椅 \n后轮支撑车技\n生奶油 \n搅拌器\n胡须\n威士忌 \n哨子\n白色\n白宫 \n白葡萄酒 \n白板 \n便门\n宽的\n挥动\n假发 \nWii \nWii手柄\n荒野\n角马\n野火\n野花 \n野生动物 \n柳树 \n风 \n风铃 \n风电场\n风力涡轮机 \n风车 \n窗户\n窗台花盆箱 \n橱窗展示 \n窗框 \n纱窗 \n靠窗的座位\n窗台\n雨刮器\n挡风玻璃 \n有风的\n酒瓶 \n冷酒器\n酒柜 \n酒窖 \n酒杯 \n酒架 \n品酒\n酒庄 \n翅膀\n冬天 \n冬瓜 \n冬天的早晨 \n冬季场景\n冬季运动 \n冬季风暴 \n电线\n紫藤 \n巫婆\n女巫帽子 \n炒锅\n狼 \n女人 \n木头\n林鸳鸯\n木地板 \n木墙 \n烧木炉\n木匙 \n林地 \n啄木鸟 \n木工刨\n羊毛 \n工作 \n练习卡 \n工作台 \n工人 \n工作场所 \n车间 \n世界 \n蠕虫 \n敬拜 \n伤口\n包\n裹身裙 \n包装纸\n搏斗\n摔跤手\n皱纹\n腕带\n写\n作家\n手写/字迹\n毛笔\n写字桌\n游艇\n牦牛 \n院子\n黄色\n瑜伽 \n瑜伽垫 \n酸奶 \n轭 \n蛋黄 \n青年 \n青年旅馆\n蒙古包\n斑马 \n斑马线 \n禅意花园 \n拉链\n拉链 \n僵尸 \n粽子\n动物园\n"
  },
  {
    "path": "ram/data/ram_tag_list_threshold.txt",
    "content": "0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.71\n0.75\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.61\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.7\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.82\n0.8\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.85\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.77\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.89\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.78\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.9\n0.65\n0.83\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.79\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.79\n0.65\n0.63\n0.65\n0.87\n0.8\n0.46\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.8\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.84\n0.65\n0.65\n0.79\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.81\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.83\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.77\n0.87\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.85\n0.65\n0.68\n0.65\n0.8\n0.65\n0.65\n0.75\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.8\n0.8\n0.79\n0.65\n0.85\n0.65\n0.65\n0.65\n0.9\n0.65\n0.89\n0.8\n0.65\n0.65\n0.65\n0.76\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n1\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.89\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.71\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.8\n0.8\n0.9\n0.65\n0.85\n0.8\n0.8\n0.8\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.75\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.63\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.71\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.9\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.71\n0.65\n0.8\n0.76\n0.85\n0.8\n0.65\n0.65\n0.8\n0.65\n0.79\n0.65\n0.75\n0.65\n0.8\n0.65\n0.86\n0.65\n0.65\n0.9\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.73\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.8\n0.75\n0.65\n0.65\n0.65\n0.65\n0.8\n0.85\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.77\n0.65\n0.65\n0.65\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.6\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.74\n0.65\n0.65\n0.67\n0.65\n0.65\n0.8\n0.65\n0.65\n0.85\n0.65\n0.8\n0.65\n0.65\n0.84\n0.8\n0.8\n0.8\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.89\n0.65\n0.65\n0.65\n0.83\n0.65\n0.65\n0.65\n0.65\n0.6\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.77\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.74\n0.65\n0.65\n0.66\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.84\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.88\n0.65\n0.65\n0.8\n0.65\n0.65\n0.7\n0.65\n0.65\n0.65\n0.9\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.82\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.75\n0.65\n0.7\n0.9\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.88\n0.65\n0.65\n1\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.71\n0.65\n0.65\n0.65\n0.79\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.88\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.82\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.87\n0.65\n0.66\n0.65\n0.84\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.84\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.5\n0.65\n0.64\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.81\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.84\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.8\n0.65\n0.85\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.73\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.82\n0.8\n0.65\n0.65\n0.65\n0.84\n0.9\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.64\n0.65\n0.65\n0.65\n0.8\n0.8\n0.87\n0.65\n0.65\n0.78\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.74\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.83\n0.89\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.8\n0.84\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.81\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.7\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.82\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.87\n0.65\n0.9\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.73\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.89\n0.8\n0.65\n0.9\n0.65\n1\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.89\n0.89\n0.65\n0.65\n0.65\n0.8\n0.75\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.88\n0.65\n0.8\n0.65\n0.65\n0.8\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.9\n0.57\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.8\n0.79\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.89\n0.8\n0.65\n0.8\n0.65\n0.8\n0.65\n0.81\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.84\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.8\n0.83\n0.65\n0.65\n0.8\n0.65\n0.65\n0.72\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n1\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.69\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.71\n0.65\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.85\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.9\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.85\n0.65\n0.65\n0.8\n0.65\n0.89\n0.65\n0.65\n0.9\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.86\n0.65\n0.77\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.75\n0.8\n0.65\n0.8\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.82\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.83\n0.65\n0.65\n0.92\n0.89\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.75\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.85\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.87\n0.65\n0.79\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.83\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.7\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.65\n0.65\n0.65\n0.65\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.8\n0.82\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n1\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.64\n0.65\n0.65\n0.63\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.76\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.65\n0.75\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.87\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.82\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.89\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.65\n0.73\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.86\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.9\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.86\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.69\n0.65\n0.65\n0.65\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.72\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.9\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.45\n0.8\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.51\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.66\n0.65\n0.8\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.81\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.75\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.66\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.65\n0.85\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.81\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.79\n0.75\n0.65\n0.65\n0.8\n0.65\n0.67\n0.8\n0.8\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.81\n0.8\n0.65\n0.65\n0.9\n0.65\n0.79\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.77\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.74\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.6\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.89\n0.8\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.9\n0.75\n0.65\n0.65\n0.65\n0.8\n0.6\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.84\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.85\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.63\n0.65\n0.65\n0.65\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.84\n0.65\n0.65\n0.8\n0.65\n0.81\n0.8\n0.8\n0.8\n0.82\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.65\n0.88\n0.65\n0.8\n0.65\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n1\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.74\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.9\n0.86\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.64\n0.65\n0.65\n0.8\n0.8\n0.65\n0.87\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.7\n0.65\n0.65\n0.8\n0.65\n0.65\n0.75\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.85\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.71\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.73\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.75\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.88\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.81\n0.65\n0.65\n0.8\n0.65\n0.65\n0.9\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.9\n0.65\n0.65\n0.65\n0.65\n0.7\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.77\n0.65\n0.65\n0.65\n0.65\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.57\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.76\n1\n0.8\n0.65\n0.65\n0.58\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n1\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.8\n0.9\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.68\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.99\n0.8\n0.77\n0.65\n0.9\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.8\n0.8\n0.65\n0.7\n0.65\n0.65\n0.8\n0.9\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.77\n0.65\n0.65\n0.65\n0.65\n0.79\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.52\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.86\n0.65\n0.65\n0.8\n0.56\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.72\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.8\n0.6\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.89\n0.85\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.75\n0.65\n0.65\n0.65\n0.65\n0.54\n1\n0.65\n0.65\n0.75\n0.65\n0.75\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.9\n0.62\n0.65\n0.65\n0.65\n0.65\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.82\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.74\n0.8\n0.65\n0.8\n0.8\n0.7\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.8\n0.8\n0.8\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.8\n0.8\n0.84\n0.8\n0.65\n0.65\n0.8\n0.75\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.82\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.84\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.8\n0.65\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.74\n0.65\n0.8\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.65\n0.65\n0.85\n0.65\n0.9\n0.9\n0.65\n0.65\n0.65\n0.63\n0.82\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.65\n0.74\n0.9\n0.65\n0.8\n0.65\n0.65\n0.58\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.75\n0.65\n0.65\n0.8\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.87\n0.65\n0.65\n0.65\n0.8\n0.65\n0.64\n0.65\n0.65\n0.65\n0.8\n0.87\n0.65\n0.65\n0.8\n0.9\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.83\n0.65\n0.65\n0.8\n0.65\n0.9\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.78\n0.65\n0.8\n0.65\n0.9\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.9\n0.65\n0.88\n0.8\n0.65\n0.65\n0.65\n0.81\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.77\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.8\n0.65\n0.65\n0.65\n1\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.85\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.88\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.65\n0.65\n0.65\n0.65\n0.68\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.9\n0.65\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.81\n0.65\n0.65\n0.65\n0.8\n0.85\n0.65\n0.77\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.8\n0.8\n0.9\n0.65\n0.65\n0.89\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.8\n0.65\n0.65\n0.65\n0.88\n0.8\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.82\n0.65\n0.8\n0.74\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.85\n0.65\n0.65\n0.85\n0.65\n0.65\n0.65\n0.65\n0.7\n0.7\n0.8\n0.65\n0.65\n0.65\n0.65\n0.87\n0.8\n0.65\n0.65\n0.65\n0.89\n0.85\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.7\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.9\n0.8\n0.8\n0.65\n0.66\n0.57\n0.65\n0.65\n0.65\n0.49\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.65\n0.65\n0.65\n0.8\n0.65\n0.8\n0.8\n0.86\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.89\n0.65\n0.65\n0.65\n0.65\n0.65\n0.65\n0.76\n"
  },
  {
    "path": "ram/data/tag_list.txt",
    "content": "tennis\nbear cub\nobservatory\nbicycle\nhillside\njudge\nwatercolor illustration\ngranite\nlobster\nlivery\nstone\nceramic\nranch\ncloth\nsmile\nbuilding\ntattoo\ncricketer\ncheek\npear\nsource\nwinter\nsurface\nspray\nceremony\nmagic\ncurve\ncontainer\nfair\nmedicine\nbaby\ntennis racquet\nornament\nbamboo\nduckling\nsong\nsafari\nteam presentation\ndaffodil\ncross\ntoothpaste\nshield\nfashion model\ncapsule\nmap\ncreek\nglass house\nglass plate\nsiding\ncorner\nwater buffalo\nbison\nfigure skater\ndiploma\ntire\nrace\ncable car\nbrain\ngas stove\nsoap bubble\npalette\nsnowboard\nschool child\ntrench coat\nmonk\nfiber\nkitchen window\nsunglass\ncoffee\nsecurity\nstrawberry\npenguin\ntree root\nloaf\nengagement ring\nlamb\nvector cartoon illustration\nsandwich\nmountain village\nshape\ncharm\nfiction\nknot\ngreenhouse\nsushi\ntext\ndisaster\ntrophy\ngang\nstrap\nsoccer game\ncardinal\ntee\nturtle\nwater surface\ngrassland\ndolphin\nstore\ndirt\niceberg\npergola\nfarmer market\npublicity portrait\ntote bag\nteenage girl\nview mirror\nsession\ncommuter\ndressing room\ntricycle\nchristmas ball\nheadlight\npolice\narmchair\nchart\nyacht\nsaw\nprinter\nrock band\ngingerbread house\ntag\ntable lamp\nhockey game\nslope\nfont\nwicker basket\njewelry\nquarter\nsoftware\nweapon\npin\nworship\npainter\ngoal\nmorning light\nbike\nbaseball bat\nelevator\ncuisine\nsausage\nstunt\nwrestler\nstatue\nlanding\npillar\nwillow tree\nsea wave\nchicken\npeanut\nmuscle\nbob\ntv genre\nbathroom window\nradish\ntextile\npelican\nmarketplace\ncrest\nelevation map\ngift\nparish\ntraffic light\ncampfire\nfog\naward winner\nbeach ball\nmat\nwhite house\nplaster\nmoped\nfootball team\nsolution\nbicyclist\nbit\nplayground\ndarkness\ncake\nmaple leave\nmold\ncracker\nblueberry\nrubble\ncontainer ship\npedestrian bridge\nsnail\nparrot\nform\ncircuit\nhighlight\npickup truck\nkoala\nrain\nsystem\nweather\nraincoat\nsoccer team\nwindshield\nthunderstorm\nmike\nbird house\nbridge\ngrandfather\nrestroom\nanimation\nwilderness\nclown\nbanana\nbrown\nbraid\ndining room\nkindergarten\nlaunch event\npurple\nschool\nstairwell\nbrooch\nmovie poster image\nmountain river\nshelf\nwicket\nheadboard\nbuddha\nflower field\ndugout\ncd\nbald eagle\nlagoon\nseaweed\nagriculture\nemergency service\nmaple tree\nparachute\ncontinent\namusement park\nremote\nbun\ntackle\nhospital\ngarage door\nbirthday party\nfriendship\ngo\nmausoleum\njeep\nraccoon\nstep\nice hockey team\ncigarette\nlace dress\nforest floor\nmall\ncaptain\nmilk\ngolf course\nmeal\npicnic table\nsail\nvolleyball\ncanal\nterrace\ncomputer desk\ncaravan\nhotel\ncheerleader\nnurse\nmuseum\nmarsh\nfox\nplateau\nnight\ntwin\nletter logo\nautumn tree\npowder\nconvention\ncreature\nlighthouse\nshop window\njacket\nstork\ntaxi\ntrade\nblackboard\nolive\nroad sign\nresort\nsnowflake\ncemetery\ntravel\nevening dress\npicnic\ndrink\nwinter morning\nfootball player\nsnack\nboxing glove\ndinner party\nairline\nswing\nport\nwheelbarrow\nbathroom sink\nsweater\nambulance\ngear\noil\nwii controller\narray\nhome office\ncar show\nmixture\nprofession\ntree frog\nsquare\nfacility\ncoral reef\nsea wall\npizza\nexhibit\ndemolition\ntrout\nring\ncoffee shop\nbracelet\nbean\nlip\nfencing\nlandscape\nsitting\npackage\nmetal\nbust\nking\nhair\nwindow seat\nwildlife\ntrunk\ngreenery\nstencil\nfire hydrant\nbridesmaid\nplaza\nalps\ntower bridge\ncrop top\ncrossing\ncinema\npedestrian crossing\nfamily\nshopping cart\nstomach\nchurch building\nscreen door\nskater\nsoccer field\nkettle\nmussel\nraindrop\ncandy cane\nwater lily\nflower girl\ndesert\nenclosure\nchristmas light\nkitchen\ncaterpillar\nplaid\nbath\nbush\nmud\nballet\nknee\nadult\nraft\nsea view\ncactus\noffice chair\noverall\nrim\nscaffolding\npig\ncover\nposter page\nsprinkle\nchandelier\nalgae\ntraffic\nsurfboard\nbook\nfilming\nflash\nmansion\ncamouflage\ntrouser\nticket\nweed\ncab\ntrench\nelephant\nhuddle\nsphere\nchristmas decoration\ncity\nlaunch\ndoll\nchristmas ornament\nfabric\nbikini\nbiplane\nbreakfast\nneighbourhood\nrace track\nfoliage\navocado\nschool bus\nfootwear\nhighway\nocean view\nart vector illustration\nwall clock\ncurtain\nteenager\nkitchen area\nrobot\ntusk\nlounge chair\nbeam\npaddle\ncamel\nlid\nworld map\ncity view\nnewlywed\ncargo ship\nyellow\nexhibition\nbend\nnovel\nwool\nontario\nbread\ncampus\ncoastline\ncutting board\nbooth\ntable top\ncarpet\nbeach chair\nworkout\nstreet food\nfun\ncostumer film designer\ngadget\nartist\nfishing village\nbuilder\nviolinist\niphone\nspider web\ntraffic sign\nruin\nrescue\nclipboard\nseal\nfilm director\npaw\nnursery\nintersection\ntomato sauce\ntaste\npaddy field\nchristmas tree\nwave\nstool\nwatering can\nrug\ndaytime\nsubway station\ncraft\npine forest\nblack\nplanet\nmotif\nchristmas market\nglass window\ncollege\nwheat\ndamage\nrectangle\npicture frame\nchess\nguest room\nstreet corner\nreligion\nseed\npuzzle\nfreeway\nbeauty\nocean\nwatch\nmother\ngarage\nquote\ndj\nsupporter\nhip hop artist\nmuffin\neiffel tower\ncash\nfirefighter\ncauliflower\nbunker\nsled\nmanicure\nshark\nstall\njungle\nfamily home\ntour bus\nchimney\ntouchdown\nroundabout\ncoyote\nstreet scene\ntank\nwedding dress\nmantle\nbedroom window\ncoconut\nchapel\ngoat\nliving space\nrock wall\npolka dot\nrailway\nmandala\nmango\nlesson\nmountain landscape\nteam photo\nbookshelf\nmeter\nbulldog\nevening sun\nstick\ncard\npink\nfish pond\npaint\npill\ncart\npea\nvan\nalbum\nfootball college game\nmountain pass\ndoughnut\nski slope\nmatch\nofficial\nshadow\norgan\ncelebration\ncoin\nlog cabin\nfirework display\npresent\ntwig\nchef\nconfetti\nfootpath\ntour\nponytail\nartwork\nrace car\nclub\nseason\nhose\npencil\naircraft\nrock formation\nwardrobe\nparticipant\npolitician\nengineer\npeace\nfilter\nsailing boat\nwater bottle\nservice dog\npoodle\nloki\nstatesman\nsleeping bag\noutskirt\nclock\nfactory\noak tree\nphysician\ncolor\nroom\nstairway\ncompany\nlady\ngraph\nfaucet\ntablecloth\nsubway train\nchocolate chip cookie\nheadquarters\nscrew\ngoggle\nhalloween\ncity street\nswirl\ncord\nforward\nbone\nbedding\narchway\nwig\nlobby\nmask\nattic\nkitchen table\nskylight\nfire\nexit\noil painting\npassenger\nmeditation\nsalmon\nfedora\nrubber stamp\norange juice\narch\nscientist\nstroll\nmanhattan\nfloat\nbaseball uniform\ncircle\nchurch\ndecker bus\ncompetitor\nzoo\nbasketball team\ntourist\ndaughter\nsilverware\nceiling fan\nbirth\nvase\njack\nmushroom\nspiral\ncage\nlimb\nsalad\nad\ncontrol\nearth\nparty\nbolt\ntractor\nbarley\nwedding photo\nhawk\nwarehouse\nvegetable garden\nchocolate cake\ncabbage\nfloor window\nbaby shower\nmagnifying glass\ntable\nstethoscope\nreading\nmission\ncroissant\ngift box\nrocket\nforest road\ncooking\nsuite\nhill country\nmotorcycle\nbaseball player\nangle\ndrug\nsport association\nchampionship\nfamily portrait\nflorist\nsoftball\negret\noffice\nplywood\njockey\nmosque\nbrunch\nbeanie\noffice building\npattern\ncalendar\nindoor\npepper\nledge\ntrail\nfuel\nlaptop computer\ntennis shoe\ndeck chair\nguitarist\nbarn\nsurgery\ncartoon illustration\nnebula\nrailroad\nmountain goat\ngoose\ncar door\ncheer\nliquid\nhardwood floor\npathway\nacorn\ngull\nairliner\ncouch\nlake house\nspaghetti\npromenade\ncollection\ngarden\nbank\nrobin\ntennis ball\npeony\ngymnast\nlavender\ndeck\ntest\nriverside\nrapper\ndomino\nbride\nmouse\nbasil\nwedding couple\nocean wave\narm\nkitchen floor\ngrove\nfamily member\nbackyard\nraspberry\nforest fire\nofficer\nhibiscus\ncanyon\ncomposer\nsignature\nolive oil\nhibiscus flower\nrose\nvector icon\nsunrise\nhorseback\nmotor scooter\noffice worker\ntradition\ningredient\nwashing machine\nlighting\nbagel\nsailboat\npoliceman\nmare\ngraphic\nhalloween pumpkin\nstock\npilot\neducation\nteam\nbody\nhorse\nkimono\nbazaar\nbag\nrecording studio\nparsley\nentrance\ndenim\nvet\nhorse farm\ncharcoal\narchitecture\nglass vase\npuppy\nestuary\ntelevision show host\ncity bus\nshoulder\nbeast\nbalance\ngolfer\nroadside\ndenim jacket\nstone wall\ncounter top\napp icon\ntoast\nhead coach\nham\nwarrior\ngem\nrefrigerator\nsnowman\nconstruction worker\ncoal\nwebsite\nmorning fog\nmustard\nhuman\nowl\npuppy dog\npiggy bank\nvegetation\npirate\naction film\nmarshmallow\nthanksgiving\nbusiness\ndisease\nsignage\ngreeting\nskate park\ntile\nmouth\nspinach\nvacation\nleader\nshrine\nwalker\nscience fiction film\nbill\nrabbit\nmotor boat\nbar\nradio\nbarge\ntail\nchainsaw\ngallery\nrainbow\npasta\npadlock\nweb\npastry\nink\nreef\nschool uniform\nshawl\ntreasure\npeach\ndinner table\ninjury\nharbor\nwitch\ncar dealership\nlitter\ngesture\ndocumentary\nmarriage\nsea shell\npriest\ndome\nkit\nicon\nseaside\nbucket\nentertainment\nstable\nhat\npuddle\nsock\nshopper\ntechnology\nharbour\norbit\nantler\ntube\nflag waving\ncook\ntight\ncommander\nfarmland\nswitch\nhiker\nwedding ceremony\naward ceremony\nchampion\nchopstick\nfarmhouse\nperformer\nspike\naccident\ncruise ship\npassenger train\nattraction\nentertainer\nrear view\nsidewalk\nparade\nracing\nplane\nritual\npeacock\npocket\nplum\ndrop\ncarrot\nfloor\nsunset\ntroop\narchitect\ncoffee table\ndust\noutline\nleather\ncharity event\nheat\nwhale\nlaundry\ncoconut tree\ncrosswalk\npony\nant\npipe\nstring\ncoat\nangel\nbeef\nchurch tower\ndish\npitch\ncupboard\nthermometer\ndirt field\nfireworks\nminute\ncane\npajama\nflower garden\nautumn\ntrash can\ndachshund\nbanana tree\ntray\nmoose\nroadway\ncarnival\nantenna\npole\ncastle wall\nram\ncattle\nhay\ncookie\nswimmer\nbaseball team\nstrait\nhedge\njet\nfire pit\noctopus\ncalf\ncube\nopera\ncardboard box\ntiara\nkitchen sink\nprairie\nbowl\ngalaxy\nstraw hat\nlinen\nski resort\nstitch\nstreet lamp\nmotorist\nicicle\nstain\nflora\ndrain\nkitchen cabinet\ndecor\nbouquet\npound\ninterior design\nnail polish\nfigurine\ntomb\ndisc\ntwist\nblouse\nribbon\nfigure\nburger\ncork\nsoccer goalkeeper\ntrain bridge\ndrinking water\ndew\nbaker\nstorm cloud\ntarmac\ntv drama\nsponge\nmagnet\nsailor\nentry\nswan\nexercise\nsloth\njewel\nscuba diver\nbite\ncat tree\ntent\ncan\ntennis match\necosystem\npicket fence\npalm\ntrain car\nfrying pan\nrally\ntablet pc\nreindeer\nimage\nwolf\nchin\nconservatory\nflood water\ncityscape\nbeach sand\ncar park\npavement\nfarm field\nswimming\nwinter storm\nstem\npillow\ninning\ngorilla\ndesk\navenue\nfern\nmoney\npearl\ntrain station\nskillet\nnap\nbarber\nlibrary\nfreezer\nlabel\nrainforest\nparking sign\nmirror\nwing\nnoodle\npress room\nsculpture\ntablet\nviewer\nprayer\nmini\nmechanic\nlaugh\nrice field\nhand\nmustache\nmountain road\ncatwalk\nconference\ncape\ninstallation\nmusician\nstream\nmachine\nspeech\ncrocodile\nsoccer match\ntown square\npassport\npost box\npoint\nstone building\nmotorway\nmix\ndentist\nbusinessperson\nhappiness\nboat\nvineyard\ntreadmill\nglass wall\nwater droplet\ncoffee mug\ngraduate\nsunflower\nparliament\nshepherd\nmovie\nwine\norchard\ntulip\nmotherboard\ncup\nbroom\nspot\ndrawing\npolo shirt\ngraduation\nfilm producer\nmoonlight\nglow\nfilm format\nt shirt\nrock face\nsword\nclinic\nfestival day\nmeadow\nstaple\npupil\ntraining ground\nrider\nflower\nfoal\nwharf\nfoot bridge\nshooting\ntop\nmast\npolice car\nrobe\nwedding bouquet\nstop sign\nbirthday cake\nglitter\nbutter\nscooter\ntundra\nsuperhero\npocket watch\ninscription\nyoungster\nfruit tree\nmovie poster\nengine\nfoundation\nmotorcyclist\ntake\nwoman\nantelope\ncountry artist\nroad trip\ntypewriter\ntuxedo\nbrand\npine\nbathroom\nparadise\ntexture\nballoon\ndining table\nhome\ncomputer screen\nactor\nclip\ntv tower\npanorama\nsummit\ncat\nplot\neagle\ndancer\npup\nstudio shot\ntear\nbird bath\nclassroom\nbookstore\ncity wall\ntv programme\nblade\neasel\nbuttercream\nsweet\ndesigner\ndiamond\nhandshake\nherb\ncorn field\nseafront\nconcrete\nstreet artist\ngas\nstamp\nwindow display\npaper\nnote\npint\nquarry\nresearch\nfixture\nmanager\nsoil\nleopard\nboard game\nladder\nstop light\nisland\nramp\nfootball match\nicing\ndrill\ncurrency\nsummer evening\ntopping\npyramid\npomegranate\ncell\nivy\nsquad\nscenery\ncomputer\nlocomotive\nsurf\nmascot\ndune\npath\nduck\ntwilight\nwire\nbow tie\nstrike\ncormorant\ncar wash\ncrane\nmarket\nphilosopher\nalarm clock\ncamera\nbirch\ngreeting card\nplain\nclay\ndonut\nlock\nmoth\nlaboratory\nfan\nviolin\njazz fusion artist\nmountain biker\nterrain\nmagazine\npickup\ncomedy film\nsmartphone\nfilm\nbed\nmicrowave oven\ntournament\nlawn\ncar window\nalligator\nscreen\njetty\nshopping bag\nlandscape view\ncabinetry\nfriendly match\nthing\npetal\nshopping center\ntransport\nballet dancer\nshoreline\nprincess\ncar seat\nparking meter\ngreen\nvodka\nband\nrock\ncostume\nwarning sign\nstrip\nplaque\nwheelchair\nheadband\nginger\ndice\nmedia\nhairdresser\npress\nliving room\nstove\nplayer\ncherry\nworkshop\ncarving\nembroidery\ndoodle\nadventure\nrugby player\nmonument\nbrush\nmarker\nloft\npostcard\ncollage\nball\nprofessor\ndresser\ngig\nfestival\nblackbird\nmakeup artist\nvideo camera\nsticker\npeak\nwildflower\nsanta hat\nrodeo\nwedding photographer\nguy\nstaff\nwaterfall\noperation\ndefender\nfalcon\nhaze\nindividual\ngentleman\ngreyhound\nrocking chair\nrice\ngarbage\nplatter\nchocolate\nsplash\nbusiness suit\ncheetah\nvalley\nmaze\ntrampoline\ngarland\nslalom\nunicorn\ntree stump\npainting\nromance\nfight\nalcohol\nghost\nfondant\nspa\nshutter\ndeath\ndemonstration\ncotton\npier\nflea market\nhistory\nsavannah\nfist\naisle\ncrew\njug\npose\nanchor\nteapot\nboat house\nbusiness team\ntripod\nbee\npebble\nmattress\ncanvas\nhallway\ncampaign\npod\nlake district\narticle\nwhite\nsofa\nhoney\nmarathon\npancake\ntourist attraction\nwedding gown\nbattle\nshelving\nsea\nsheet music\npie\nyarn\nconstruction site\nflyer\ntie\nstar\nlettuce\nmartial artist\ndart\nstraw\nreflection\nconference room\ntemperature\nrugby\nmosquito\nphysicist\nrock climber\ncrash\nbackdrop\ntoilet seat\nsand castle\nwater park\ntoy car\nwaste\nluxury\nhangar\nrv\ntree trunk\nboard\ngold\nproject picture\ncap\ncottage\nrelief\nattire\nmicroscope\nbattery\nroll\nline\nparking garage\ncrystal\nbroadcasting\nbrick wall\nlab\nflooring\nmeeting\n3d cg rendering\ndesktop computer\ncowboy\nsailing ship\njunction\nhairstyle\nhomework\nprofile\nmodel\nflower pot\nstreet light\nsalt lake\nmaple\nspace\nblizzard\nthrow\nzebras\nbrochure\nconstellation\nbeak\nkilt\npond\nblue sky\nsneaker\nsand dune\nmorning sun\nalmond\ngrill\ncurl\nbasketball girl game\nchameleon\ntoilet bowl\nprince\nkeyboard\nqueen\ncomputer monitor\nwriting\ncrown\nbasilica\nkiss\nhouse\nparking\nfootball competition\nshell\nsport equipment\ncomedy\nbaboon\nvendor\nrise building\nwrap\nfood truck\ncat bed\nrickshaw\nflare\nteal\nnectar\neclipse\nvehicle\nsteam locomotive\ngorge\ncow\nchristmas card\ndemonstrator\nmemorial\ntowel\njewellery\ntrain\nfrisbee\nbaseball game\nfur\nafternoon sun\ncommunity\nsparkler\nbandage\nfirework\ndollar\npasture\nvideo\nbus\ntree house\nseashore\nfield\nhamburger\nsouvenir\nhedgehog\nworm\npine cone\nosprey\ndinosaur\nvegetable\njunk\nposter\narmy\nwinger\nbundle\nstage\ngrowth\nwedding party\nservice\nblanket\nruler\neye\ncredit card\ncastle\ndiner\nhut\nelk\nhard rock artist\nnun\ndog breed\nnest\ndrama film\nnumber icon\nwater tank\ngiraffe\naltar\npavilion\ntv personality\nsuv\nstreet vendor\nstreet sign\nditch\ndebris\nfoam\ntakeoff\nspice\nmountain lake\ntea\norchestra\nspacecraft\ncounter\nabbey\nmountain\nhydrangea\nracer\norange tree\ntide\ncowboy hat\nrapid\ntown\nwild\nherd\nvein\ndriveway\njar\nbark\nillustration\nhorror film\ncorn\nstroller\nindustry\nmountain stream\ngym\nneckline\npan\nclient\nspectator\neggplant\ncamper\nfawn\nhoodie\nmeat\nlemonade\nfood market\nslum\ncomic book character\nflower market\nlove\npalace\ngun\nheel\nshopping street\nshooting basketball guard\nfamily photo\nrooftop\nlaundry basket\nairport runway\nhorn\nface mask\nflight\nappetizer\nviolet\ncountry lane\ncement\ninstrument\ntv actor\nspark\ncelebrity\naward\ncountry house\nstanding\nauction\ndate\nengagement\npuck\nadvertisement\nchair\nzebra\ndriftwood\nbumblebee\nmaple leaf\nbonnet\norange\nwater tower\ndoor\nsinger\nfloor plan\ndiscussion\ntheatre\npilgrim\nmug\nbranch\nwindow sill\nbaseball pitcher\nbakery\nlollipop\nbasketball player\ntoilet paper\nchalkboard\ncabin\nsign\nnight sky\ncannon\nfishing net\nsubmarine\nsuit\nfur coat\nwine bottle\nfolder\nstreet art\nsuspension bridge\nevening sky\nbillboard\npostage stamp\nnewspaper\ntransportation\nsurgeon\nlight\npark\nhorizon\nroad\nsand bar\ntrumpet\nlounge\ncloud forest\nbirthday celebration\nbalcony\nanime\nbeehive\numbrella\ngoldfish\nbaseball cap\nwaterhole\nceiling\ncarousel\nbackpack\nplant pot\natmosphere\nsunflower field\nspire\nvision\nwoodpecker\nchip\npool table\nlotus flower\ncone\nhumpback whale\nreservoir\nhunt\npiano\nplate\ndining area\nluggage\nskier\ndance floor\ncrow\nstair\noverpass\nopera house\nbear\njazz artist\nwater\nvessel\ncast\nyard\ncathedral\nbasketball hoop\ngraveyard\nsound\nberry\nonlooker\nfauna\nbirch tree\nretail\nhill\nskeleton\njournalist\nfrost\nbasket\nnail\ndusk\ntrash\ndawn\nclover\nhen\nvolcano\nbasketball coach\nhome decor\ncharge\nhaircut\nsense\nuniversity\nlizard\ndaisy\ntablet computer\ngrass field\nprison\nmetal artist\nbathroom mirror\nwindow frame\nchest\nflavor\npop country artist\nmarket square\nmonkey\nblog\ndeer\nspeech bubble\ndog\nindependence day\ngirl\nboy\ntartan\nfurniture\nappliance\noffice window\nfish boat\nsand box\ntv sitcom\ndrama\nsleigh\ndepression\npaper towel\nbaseball\nprotestor\ngrape\nwedding cake\ninvitation\naccessory\npick\ngrandparent\nracket\ntea plantation\noutdoors\negg\nglass bowl\nsun\norganization\nlion\npanel\nstation\nwallpaper\nhelicopter\nsalt\nvanity\npatio\nlunch\nstreet performer\nmountain range\nsoup\nbacon\npower station\ncantilever bridge\nhummingbird\nshirt\nrope\nhip\nchalk\npendant\nchoir\ntv\nlichen\nrailway bridge\nart gallery\nbartender\nwagon\nbaby elephant\naccordion\nhorseshoe\nbuilding site\nclutch\nharvest\nsavanna\ngeranium\nbusiness woman\npaddock\npatch\nbeech tree\nwar\nsuburbs\nhospital bed\nmotorcycle racer\nmoss\ngravel\ngovernment agency\ndollar bill\nfather\nfjord\nconcert\nnut\nwedding photography\nfinish line\nhome plate\nfood\nnose\nthumb\nvillage\ndining room table\nbumper\nmonster\nblackberry\nlime\nconflict\ngala\nwallet\nwrist\nhug\nmermaid\nlava\nlawyer\nfolk rock artist\narena\nonion\ntoothbrush\nfashion\nperfume\nflip\ntriangle\nwoodland\nmail\ngrasshopper\nstudio\nwood floor\nden\nracquet\ncello\nlemur\nastronaut\nglass table\nblood\ndvd\nplanter\nsilver\nleash\nmaster bedroom\nforest\nbatter\nshoe\nengraving\nopening\nproduct\ntoe\ncocktail\nmallard duck\nbike ride\noasis\nwedding ring\ncinematographer\nholly\nautograph\nfence\nice cube\ncove\npineapple\naurora\nglass bead\nproduce\napartment building\ncob\nminiature\ncockpit\nflashlight\nfrog\nsheep\ngroom\nsteel\nwatermelon\nclip art\npaper plate\nostrich\ncontour\nmural\ncub\npaisley bandanna\nwinery\nturn\nhandle\nsatellite\npost\npork\nchild\nasphalt\ngrocery store\nvulture\ntrolley\nnightclub\nbrick\ntrailer\ncompass\ncereal\ncafe\ncartoon character\nsugar\nfiction book\nglass floor\numpire\nguitar\nhamster\nprotester\nairplane\ngarment\nblazer\nrailway line\nwedding\nshoe box\nparking lot\nconstruction\ngraduation ceremony\ntram\ntelescope\ncopper\npain\nautumn forest\nguest house\npartner\ncrayon\ndip\nboot\ncorridor\ncomputer keyboard\nhockey player\nchicken coop\nbus station\ngathering\nankle\nbunk bed\nwood table\nfootball coach\nmonarch\npharmacy\nlegging\nmannequin\nfemale\ntrain track\nstack\ncanopy\ndesign element\ngrandmother\nsymbol\nbeach hut\nzucchini\nbomb\nbusinessman\nskyscraper\ntongue\ncase\nsparkle\nhighland\nballroom\nprom\nestate\ncustomer\narchipelago\ncheese\ndebate\ncarriage\nbulldozer\npumpkin\nsitting room\ngas station\nwedding reception\ncamp\ndog bed\ntower\nproperty\nriver bed\npop latin artist\nfridge\nwine glass\ncoast\nbeer\ntow truck\nfire truck\nmountain bike\nthigh\nheron\nboat ride\ngondola\nturquoise\nlake\nllama\nkitty\ntin\nwaiting room\ncoffee cup\nsocialite\nguard\ntap\nwaterway\nforehead\nlist\nerosion\nbox\nsea lion\npollen\ndam\nwasp\nsalon\ntennis tournament\nflower box\naquarium\nrain cloud\nclothing store\nlead singer\ncupcake\ntortoise\nlettering\nsport facility\ndance\ndog house\nnature\nfootball\nrooster\nfootballer\nrailway track\ncrowd\nfishing rod\nsilhouette\nwind turbine\nsari\nbus window\ncloud\ncharity\nmedal\nyoga\nevent\nveil\nfashion menswear milan week\nnews\nknife\nprint\nscreen tv\nwalnut\nfungus\nice cream\ncomputer mouse\nplay\ntribe\npicture\nvideo game\nbusiness card\nmusic festival\nrack\nenvelope\nshower\ndirt road\nmine\noyster\nmonarch butterfly\ndude\nfruit salad\npodium\nfork\nlace\ntest match\nboulder\ncricket player\nstaircase\npeninsula\nshopping\npopcorn\noak\nmarket stall\npine tree\nmountaineer\nstudent\ncloset\nhood\nhandstand\ncenterpiece\ninsect\npatient\nmakeover\ntennis player\nsheet\npark bench\napple\norganism\nhook\nturkey\ntangerine\nsibling\nshopping mall\nbird\nscarf\nsmoothie\nnet\ngrass\nnapkin\nray\neyebrow\nlaptop keyboard\nmotorbike\nwoman hand\noven\nbook cover\neaster egg\nmicrowave\nsand\nsnapshot\nsoccer ball\nmakeup\nknight\nbowling ball\nshower curtain\nflame\nlightning\nrunning\npower plant\ncrib\ncartoon\nmoat\nfashion girl\nwedding invitation\nbottle\ncliff\nmonastery\nfile photo\napartment\ncasino\ncream\nsweatshirt\nstorm\ncruise\nteddy bear\nshovel\nwind farm\nwriter\ndock\nprofessional\nhotel room\njob\nmonitor\ndonkey\npass\ninterview\nduchess\nmark\nplank\nbeard\nzombie\ntrio\nchannel\ncricket team\nwindmill\nvest\ndiagram\ncable\nwinter scene\ngolden gate bridge\nbuffalo\nstudio portrait\npagoda\nwhiskey\nfreight train\nkite\nfuture\nsteam train\nphone box\nheadset\nwood\nsnowboarder\npaper bag\nslide\ngrapefruit\nseating\nmorning\nbronze sculpture\ntheatre actor\nstump\njean\nlandmark\njam\nwaist\nwatercolor\nhammock\nlight fixture\nice\nbasin\nbeverage\nshelter\npremiere\nmound\near\nbronze\nsunlight\nstreet\nenergy\nbarn door\nhike\nfleet\nclaw\nbeach\npepperoni\nbin\ntrainer\nbuffet\narchive\ntoddler\nreferee\nbay window\ndove\nproduction company\nevening light\ngate\nfarm\nreed\nfruit stand\nexplorer\nsnow storm\nthrow pillow\nbutton\ndisplay case\nbookcase\nlead\nlipstick\nbasketball court\ncargo\nensemble\npope\nclock tower\nteen\nspeaker\nrat\nlaptop\nski\nmess\nstadium\nferry boat\nbunny\nwaterfront\ndowntown\nsink\npress conference\ndinner\ncondiment\nthread\naudience\ngrid\ncar\nplastic\npeople\nbarbecue\npigeon\nurinal\nseagull\nvolunteer\nhockey\nfir tree\npollution\ntrial\ncollar\narea\nmeeting room\ncircus\nyogurt\norangutan\nviaduct\ncomedian\ndrone\nscissor\npop rock artist\nbiscuit\npanda\nwater feature\nair balloon\nremote control\nwatercolor painting\nshow\nwalk\npost office\nbike path\nrap gangsta artist\nmicrophone\ncrack\nsunset sky\nglass\ntv show\ncartoon style\nstripe\nfoyer\nsignal\ncalligraphy\nbulb\ngardener\ncoffee bean\nspider\ntapestry\ncity skyline\nnecklace\nkitten\ntraveler\nveteran\nfrosting\nfry\ntennis court\ntank top\nbutterfly house\nmist\ndrummer\nwater level\nscale\nbaseball glove\nmusic video performer\nchampagne\ncamping\nclothing\nwater drop\ntelephone box\npen\nmorning mist\nfire engine\nporch\nopening ceremony\nstyle\npalm tree\nfashion show\nuniverse\nscratch\naxe\nottoman\nexplosion\nrib\nboutique\ngame\ncucumber\nfruit\nstone bridge\nnature reserve\ntrack\ntrain window\npunch\ntelephone pole\nvelvet\nsauce\nmoon\ncontrast\nflamingo\nbat\nvending machine\nship\nequestrian\nshade\ncomforter\npallet\nsparrow\nwii\nglaze\ngrocery\nsteeple\nsoccer player\ncontract\nadvertising\nrunner\nchimpanzee\nworld\nseat\nproject\nchihuahua\nbubble\nwillow\npedestal\nsoul hip hop artist\ncurb\ndrawer\nleaf\nbanner\nlaunch party\ncoach\ngovernment\nsnowball\ntoy\nportrait\ndoctor\nwhiteboard\nelectronic\ntiger\ngraffiti\ncolumn\nnightstand\nwhistle\nmaxi dress\nbench\nwetsuit\nbird feeder\nfootball game\nbasketball\nclass\nbathroom door\nstore window\ntext message\nwreath\nstreet view\nbinocular\npet\nfacade\ndrought\nlemon\nnew year\nnight view\nairplane window\nspecie\nrule\njaw\nwheat field\ndiet\npop artist\nhabitat\nscreenshot\nscoreboard\nshore\nmane\nquilt\nski lift\norchid\nturban\nchristmas\nairport\nmarina\nglass door\nglass bottle\nrestaurant\nconductor\nlogo\nsleep\ntape\ntomato\nriver bank\nlilac\ntooth\ntraining\npottery\nshop\nsteam engine\nmason jar\nbase\nprocession\nborder\nshoot\nfootprint\nhotdog\nbull\nstocking\nrecreation\nautomobile model\ndesign\ncountry pop artist\nriver\nretriever\ndepartment store\nauditorium\nsport car\nsupermarket\nbelt\ncricket\nwindow box\ndress shirt\nletter\nresidence\nmegaphone\npant\nwildfire\nbird nest\ncrab\nswimsuit\ncandle\nfuneral\nmill\nnational park\nplant\ncop\npower line\nperch\nblue\nfinger\nferris wheel\nglobe\nskateboard\nhelmet\nmovie theater\nuniform\nhammer\nmaterial\nkid\nwell\nbutterfly\nsideline\nfashion fall show\nplanet earth\nlift\nmale\nsauna\ngray\nflour\nsand sculpture\nprogram\ncabinet\ninfant\nwheel\naircraft model\ndough\ngarlic\nskate\narrow\nwrapping paper\nripple\nlamp\niron\nbanknote\nbeaver\nferry\ncourtyard\nbassist\ncountryside\nsteak\ncomfort\nboxer\nlaundry room\ncampsite\nbrick building\ngolf\nsubway\nheadphone\nfort\nhandbag\ndrum\nflood\nsaddle\nbass\nlabyrinth\nneedle\nsun ray\napp\nmenu\npresident\ncardigan\ndandelion\nwetland\nice hockey player\nnumber\ncity hall\nfishing\nportrait session\npug\nkey\nart print\nminister\nhurdle\nemergency\npainting artist\nflag pole\nevening\npurse\nrecipe\ngolf ball\ncoloring book\nmountain peak\nsenior\nholiday\nbud\ncousin\npantry\nlap\nskin\nflag\ntissue paper\nridge\nwire fence\nsurfer\nclimber\nphotograph\nsewing machine\ncooler\nactress\napple tree\ncancer\nstarfish\nautomobile make\ndumbbell\nbrace\ntunnel\nwindow\npaint artist\ncomposition\nschool student\ncondo\nconvertible\ncushion\nselfie\nterritory\nguide\ntree\ncourt\nshrimp\nstone house\ndress\neyelash\njuice\nbroccoli\nchain\ntourism\nmountain top\nconcept car\nfilm premiere\nlight bulb\ncafeteria\nbadge\nflower bed\ntheater\nroot\nracecar driver\nbasketball boy game\nglove\nskyline\nwall\nglacier\nairport terminal\nbug\ntrim\nrailway station\nbriefcase\nflat\nfountain\nperson\nlane\nasparagus\nart\nlantern\ndishwasher\ndirector\nsnake\nlecture\ngame controller\ntree branch\npub\nbathing suit\nqueue\nbelly\npoppy\nbow\npitcher\nice cream cone\ncave\ncandy\nroad bridge\nhost\ntraffic jam\nearring\nfile\nfoot\nwatermark overlay stamp\nmailbox\nsupercar\nrailing\nbedroom\nseafood\nwaffle\nbronze statue\nplan\nflow\nmarble\nbasketball game\nautomobile\nscene\ncypress tree\nsoldier\nskateboarder\nglass building\ncherry tree\npump\ngrain\nwildebeest\nloop\nframe\nbathtub\nsaxophone\ndiver\nstalk\nlily\nbead\nalley\nflock\nfamily room\nmanufacturing\npointer\nworker\nnavy\npotato\nteacher\nphotography\ndolly\nboardwalk\nwater fountain\nathlete\nside dish\nbay\nice hockey\nphone\nhero\nface\ngold medal\nblind\nswamp\nresearcher\nswim\nmeatball\niguana\nleather jacket\njellyfish\nsite\nsmoke\ntraffic signal\nmelon\nbeetle\ncalculator\nskirt\nplantation\nsculptor\nbarrier\ncatcher\nsecurity guard\nsketch\nawning\nsteering wheel\nmountain view\nbus stop\npool\nleg\nspotlight\napron\nmineral\ninlet\nsleeve\ntorch\nemotion\nmarch\npolice officer\nperformance\nlamp post\nfishing boat\nsummer\npresentation\nsaucer\nsuitcase\nsupermodel\ngoalkeeper\nshrub\nrock artist\ndocument\nbeach house\nman\nblue artist\ncigar\nrailroad track\ngown\nmosaic\nbungalow\nalphabet\nbaseball field\nshed\npedestrian\nrail\nsoap\nkitchen counter\ndessert\ndunk\nblossom\nconversation\nfruit market\nglass jar\nmilitary\nbeer bottle\nphotographer\ntennis racket\ncompetition\nescalator\nbell tower\nstilt\nballerina\ntelevision\nfeather\nfence post\nrear\ndahlia\nred carpet\ntub\nhole\nfortress\npack\ntelephone\ncardboard\ncity park\nplatform\ncollege student\narch bridge\nwind\nblender\nbloom\nice rink\nbirthday\nraven\nfairy\nembankment\nhall\nflower shop\nsuburb\nbarrel\nbiker\nsteam\ndragonfly\nformation\nelectricity\nbusiness people\nsymmetry\nwalkway\nfisherman\ngas mask\nloch\nyouth\nhanger\ndot\nfish\nstreet market\nanimation film\ncrime fiction film\nboar\nemblem\nhalloween costume\nkangaroo\ncouple\nspoon\nsquirrel\nneon sign\nsky\noffice desk\nbeauty salon\nbreakwater\nfashion look\ntoaster\nauthor\nnews conference\noutdoor\ncanoe\ndragon\ntool\nshopping centre\nladybug\nswimming pool\nlandscaping\nski pole\nred\ntruck\nfly\ntemple\nlevel\nsunday\nrailroad bridge\ncar mirror\nlawn mower\nflute\naircraft carrier\nfashion menswear london week\nsunshine\ntile floor\nskull\nfossil\nflower arrangement\ndiaper\nsea turtle\ncherry blossom\nfireman\nshack\nlens\nwaiter\nanimal\nbasement\nsnow\nautumn park\nglass box\nkick\nhead\nanniversary\nvine\nback\npaper lantern\nfish tank\ncellphone\nsilk\ncoral\nnotebook\nphoto\ngazebo\nketchup\ndriver\nfarmer\nbonfire\nchestnut\nphotoshoot\nfootball field\nolive tree\npheasant\nsandal\ntoilet\nfireplace\nmusic\ndeity\nfish market\nfig\nbell\nneck\ngrave\nvilla\ncyclist\ncrate\ngrey\nasphalt road\nsoccer\nhostel\nmunicipality\ncourthouse\nroof\nend table\npot\nsedan\nstructure\nfolk artist\nsport\nsport team\nprotest\nsyringe\nfashion designer\njersey\nheart shape\nkayak\nstare\nsit with\ndirect\nread\nphotograph\nspin\nteach\nlaugh\ncarve\ngrow on\nwarm\nwatch\nstretch\nsmell\ndecorate\nshine\nlight\ndance\nsend\npark\nchase\ncollect\nlead\nkiss\nlead to\nlick\nsmile\ncheer\nsit\npoint\nblock\nrock\ndrop\ncut\nski\nwrap\nlose\nserve\nprovide\nsleep\ndress\nembrace\nburn\npack\nstir\ncreate\ntouch\nwash\nstick\nreveal\nshop\ntrain\npaint\ngroom\nhunt\nbloom\nplay\npay\nbrush\nshoot\nhold\npicture\ncarry\nsip\ncontain\nturn\npour\npitch\ngive\nadd\nblow\nlook in\nshow\nwalk\nilluminate\nkneel\ncover\ndrag\npost\npresent\nfit\noperate\nfish\nrace\nwrite\ndeliver\npeel\npush\nrun\nsit around\nbuy\njump\nwalk on\nattend\nclean\nsell\nride on\nmount\nhost\ndry\nplant\nsing\nrow\nshake\nperch\nride\nfight\nskateboard\nlive\ncall\nsurround\npractice\nplay on\nwork on\nstep\nrelax\nhit\nfall in\nflow\ngreet\nlaunch\nwear\nhang on\ndrive\nsit in\nbreak\nlearn\nfly\nconnect\ndisplay\nlocate\ncompete\ngo for\nsail\nlift\ntoast\nhelp\nrun on\nreflect\npose\nscratch\nframe\ndribble\nherd\nenter\nexit\nplace\ninspect\nbuild\npick\nfill\ngrind\nskate\noffer\nfloat\nsit by\nstand\nrelease\nrest\nsinge\nclimb\ntie\nmark\nlay\nstand around\ncapture\nset\nland\nswinge\nrun in\nkick\nlean\nhead\nsign\napproach\nswim\nclose\ncrash\ncontrol\nfall\nremove\nrepair\nopen\nappear\ntravel\nload\nmiss\ncheck\nsurf\nmoor\nsmoke\ndrink\nboard\nseat\nfeed\nrise\nsit on\nswing\ngrow\nstrike\ndate\nslide\nshare\ngraze\njump in\nlie\nextrude\nroll\nmove\ngather\neat\npull\nrun through\nsqueeze\nlay on\ndraw\nplay with\nwave\nassemble\nperform\nmarch\nscore\nattach\nadjust\nhang\nhug\nsleep on\nthrow\nlive in\ntalk\npet\nwork\nrun with\nsee\nflip\ncatch\ncook\nreceive\ncelebrate\nlook\nclassic\nbridal\nindoor\nindustrial\nteenage\nmini\ngrassy\naged\nlong\nwarm\nlight\nhandsome\nhappy\nthree\npregnant\ncircular\nurban\nsilver\nceramic\n3d\ngreen\nblonde\ngolden\ndark\ntropical\nripe\ndeep\nfat\nmusical\ngiant\nmedical\nmedieval\nbare\nstunning\nbold\ngeographical\nhuge\nplastic\nfoggy\nstormy\ngothic\nbiological\nempty\nclear\nantique\npink\nsteep\nbrown\nstriped\naerial\nrainy\ncool\nflying\ncommercial\npurple\ntrendy\nblank\nhaired\ndead\nwooden\nflat\nhigh\nbeige\npanoramic\nangry\ndozen\nrural\nsolar\nbig\nsmall\nstained\nthick\nmany\nfresh\nclean\nstrong\nabstract\ncrowded\nretro\ndry\ngorgeous\nmartial\nmodern\nblue\ncloudy\nlow\nfour\noutdoor\nsingle\nmuch\nbeautiful\nsnowy\npretty\nnew\nshort\nsunny\nclosed\nrocky\nred\ntwo\ndouble\nmale\ngray\nfive\ncolorful\nautomotive\nvarious\none\nold\nrusty\ntall\nwild\nnarrow\nnatural\nseveral\nfrozen\ntextured\nlush\nyoung\nhot\nmixed\nwhite\nfloat\nquiet\nround\nbright\nreligious\nfemale\nhistorical\nshiny\ntraditional\ntourist\nyellow\nbald\ncoastal\nlovely\nlittle\nbroken\nromantic\nwide\nroyal\nrich\nopen\ncute\nancient\ncold\npolitical\nelderly\ngold\nfull\nrustic\nmetallic\nfloral\nsad\nwet\nfancy\nsenior\ntiny\nstylish\nlarge\nfrosty\norange\ntransparent\nelectronic\nshallow\nscared\narmed\ndirty\nhistoric\nblack\nfew\nwindy\nsome\nsquare\nornamental\nsandy\nthin"
  },
  {
    "path": "ram/models/__init__.py",
    "content": "from .ram import ram\nfrom .tag2text import tag2text\n"
  },
  {
    "path": "ram/models/bert.py",
    "content": "'''\n * Copyright (c) 2022, salesforce.com, inc.\n * All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause\n * By Junnan Li\n * Based on huggingface code base\n * https://github.com/huggingface/transformers/blob/v4.15.0/src/transformers/models/bert\n'''\n\nimport math\nimport os\nimport warnings\nfrom dataclasses import dataclass\nfrom typing import Optional, Tuple\n\nimport torch\nfrom torch import Tensor, device, dtype, nn\nimport torch.utils.checkpoint\nfrom torch import nn\nfrom torch.nn import CrossEntropyLoss\nimport torch.nn.functional as F\n\nfrom transformers.activations import ACT2FN\nfrom transformers.file_utils import (\n    ModelOutput,\n)\nfrom transformers.modeling_outputs import (\n    BaseModelOutputWithPastAndCrossAttentions,\n    BaseModelOutputWithPoolingAndCrossAttentions,\n    CausalLMOutputWithCrossAttentions,\n    MaskedLMOutput,\n    MultipleChoiceModelOutput,\n    NextSentencePredictorOutput,\n    QuestionAnsweringModelOutput,\n    SequenceClassifierOutput,\n    TokenClassifierOutput,\n)\nfrom transformers.modeling_utils import (\n    PreTrainedModel,\n    apply_chunking_to_forward,\n    find_pruneable_heads_and_indices,\n    prune_linear_layer,\n)\nfrom transformers.utils import logging\nfrom transformers.models.bert.configuration_bert import BertConfig\n\n\nlogger = logging.get_logger(__name__)\n\n\nclass BertEmbeddings_nopos(nn.Module):\n    \"\"\"Construct the embeddings from word and position embeddings.\"\"\"\n\n    def __init__(self, config):\n        super().__init__()\n        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)\n        # self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)\n\n        # self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load\n        # any TensorFlow checkpoint file\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n        # position_ids (1, len position emb) is contiguous in memory and exported when serialized\n        # self.register_buffer(\"position_ids\", torch.arange(config.max_position_embeddings).expand((1, -1)))\n        # self.position_embedding_type = getattr(config, \"position_embedding_type\", \"absolute\")\n        \n        self.config = config\n\n    def forward(\n        self, input_ids=None, position_ids=None, inputs_embeds=None, past_key_values_length=0\n    ):\n        if input_ids is not None:\n            input_shape = input_ids.size()\n        else:\n            input_shape = inputs_embeds.size()[:-1]\n\n        seq_length = input_shape[1]\n\n        # if position_ids is None:\n            # position_ids = self.position_ids[:, past_key_values_length : seq_length + past_key_values_length]\n\n        if inputs_embeds is None:\n            inputs_embeds = self.word_embeddings(input_ids)\n\n        embeddings = inputs_embeds\n\n        # if self.position_embedding_type == \"absolute\":\n        #     position_embeddings = self.position_embeddings(position_ids)\n        #     # print('add position_embeddings!!!!')\n        #     embeddings += position_embeddings\n        embeddings = self.LayerNorm(embeddings)\n        embeddings = self.dropout(embeddings)\n        return embeddings\n\n\n\n\nclass BertEmbeddings(nn.Module):\n    \"\"\"Construct the embeddings from word and position embeddings.\"\"\"\n\n    def __init__(self, config):\n        super().__init__()\n        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)\n        self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)\n\n        # self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load\n        # any TensorFlow checkpoint file\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n        # position_ids (1, len position emb) is contiguous in memory and exported when serialized\n        self.register_buffer(\"position_ids\", torch.arange(config.max_position_embeddings).expand((1, -1)))\n        self.position_embedding_type = getattr(config, \"position_embedding_type\", \"absolute\")\n        \n        self.config = config\n\n    def forward(\n        self, input_ids=None, position_ids=None, inputs_embeds=None, past_key_values_length=0\n    ):\n        if input_ids is not None:\n            input_shape = input_ids.size()\n        else:\n            input_shape = inputs_embeds.size()[:-1]\n\n        seq_length = input_shape[1]\n\n        if position_ids is None:\n            position_ids = self.position_ids[:, past_key_values_length : seq_length + past_key_values_length]\n\n        if inputs_embeds is None:\n            inputs_embeds = self.word_embeddings(input_ids)\n\n        embeddings = inputs_embeds\n\n        if self.position_embedding_type == \"absolute\":\n            position_embeddings = self.position_embeddings(position_ids)\n            # print('add position_embeddings!!!!')\n            embeddings += position_embeddings\n        embeddings = self.LayerNorm(embeddings)\n        embeddings = self.dropout(embeddings)\n        return embeddings\n\n\nclass BertSelfAttention(nn.Module):\n    def __init__(self, config, is_cross_attention):\n        super().__init__()\n        self.config = config\n        if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, \"embedding_size\"):\n            raise ValueError(\n                \"The hidden size (%d) is not a multiple of the number of attention \"\n                \"heads (%d)\" % (config.hidden_size, config.num_attention_heads)\n            )\n        \n        self.num_attention_heads = config.num_attention_heads\n        self.attention_head_size = int(config.hidden_size / config.num_attention_heads)\n        self.all_head_size = self.num_attention_heads * self.attention_head_size\n\n        self.query = nn.Linear(config.hidden_size, self.all_head_size)\n        if is_cross_attention:\n            self.key = nn.Linear(config.encoder_width, self.all_head_size)\n            self.value = nn.Linear(config.encoder_width, self.all_head_size)\n        else:\n            self.key = nn.Linear(config.hidden_size, self.all_head_size)\n            self.value = nn.Linear(config.hidden_size, self.all_head_size)\n\n        self.dropout = nn.Dropout(config.attention_probs_dropout_prob)\n        self.position_embedding_type = getattr(config, \"position_embedding_type\", \"absolute\")\n        if self.position_embedding_type == \"relative_key\" or self.position_embedding_type == \"relative_key_query\":\n            self.max_position_embeddings = config.max_position_embeddings\n            self.distance_embedding = nn.Embedding(2 * config.max_position_embeddings - 1, self.attention_head_size)\n        self.save_attention = False   \n            \n    def save_attn_gradients(self, attn_gradients):\n        self.attn_gradients = attn_gradients\n        \n    def get_attn_gradients(self):\n        return self.attn_gradients\n    \n    def save_attention_map(self, attention_map):\n        self.attention_map = attention_map\n        \n    def get_attention_map(self):\n        return self.attention_map\n    \n    def transpose_for_scores(self, x):\n        new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size)\n        x = x.view(*new_x_shape)\n        return x.permute(0, 2, 1, 3)\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_value=None,\n        output_attentions=False,\n    ):\n        mixed_query_layer = self.query(hidden_states)\n\n        # If this is instantiated as a cross-attention module, the keys\n        # and values come from an encoder; the attention mask needs to be\n        # such that the encoder's padding tokens are not attended to.\n        is_cross_attention = encoder_hidden_states is not None\n\n        if is_cross_attention:\n            # print(self.key.weight.shape)\n            key_layer = self.transpose_for_scores(self.key(encoder_hidden_states))\n            value_layer = self.transpose_for_scores(self.value(encoder_hidden_states))\n            attention_mask = encoder_attention_mask\n        elif past_key_value is not None:\n            key_layer = self.transpose_for_scores(self.key(hidden_states))\n            value_layer = self.transpose_for_scores(self.value(hidden_states))\n            key_layer = torch.cat([past_key_value[0], key_layer], dim=2)\n            value_layer = torch.cat([past_key_value[1], value_layer], dim=2)\n        else:\n            key_layer = self.transpose_for_scores(self.key(hidden_states))\n            value_layer = self.transpose_for_scores(self.value(hidden_states))\n\n        query_layer = self.transpose_for_scores(mixed_query_layer)\n\n        past_key_value = (key_layer, value_layer)\n\n        # compatible with higher versions of transformers \n        if key_layer.shape[0] > query_layer.shape[0]:\n            key_layer = key_layer[:query_layer.shape[0], :, :, :]\n            attention_mask = attention_mask[:query_layer.shape[0], :, :]\n            value_layer = value_layer[:query_layer.shape[0], :, :, :]\n\n        # Take the dot product between \"query\" and \"key\" to get the raw attention scores.\n        attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))\n\n        if self.position_embedding_type == \"relative_key\" or self.position_embedding_type == \"relative_key_query\":\n            seq_length = hidden_states.size()[1]\n            position_ids_l = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(-1, 1)\n            position_ids_r = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(1, -1)\n            distance = position_ids_l - position_ids_r\n            positional_embedding = self.distance_embedding(distance + self.max_position_embeddings - 1)\n            positional_embedding = positional_embedding.to(dtype=query_layer.dtype)  # fp16 compatibility\n\n            if self.position_embedding_type == \"relative_key\":\n                relative_position_scores = torch.einsum(\"bhld,lrd->bhlr\", query_layer, positional_embedding)\n                attention_scores = attention_scores + relative_position_scores\n            elif self.position_embedding_type == \"relative_key_query\":\n                relative_position_scores_query = torch.einsum(\"bhld,lrd->bhlr\", query_layer, positional_embedding)\n                relative_position_scores_key = torch.einsum(\"bhrd,lrd->bhlr\", key_layer, positional_embedding)\n                attention_scores = attention_scores + relative_position_scores_query + relative_position_scores_key\n\n        attention_scores = attention_scores / math.sqrt(self.attention_head_size)\n        if attention_mask is not None:\n            # Apply the attention mask is (precomputed for all layers in BertModel forward() function)\n            attention_scores = attention_scores + attention_mask\n\n        # Normalize the attention scores to probabilities.\n        attention_probs = nn.Softmax(dim=-1)(attention_scores)\n        \n        if is_cross_attention and self.save_attention:\n            self.save_attention_map(attention_probs)\n            attention_probs.register_hook(self.save_attn_gradients)         \n\n        # This is actually dropping out entire tokens to attend to, which might\n        # seem a bit unusual, but is taken from the original Transformer paper.\n        attention_probs_dropped = self.dropout(attention_probs)\n\n        # Mask heads if we want to\n        if head_mask is not None:\n            attention_probs_dropped = attention_probs_dropped * head_mask\n\n        context_layer = torch.matmul(attention_probs_dropped, value_layer)\n\n        context_layer = context_layer.permute(0, 2, 1, 3).contiguous()\n        new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)\n        context_layer = context_layer.view(*new_context_layer_shape)\n\n        outputs = (context_layer, attention_probs) if output_attentions else (context_layer,)\n\n        outputs = outputs + (past_key_value,)\n        return outputs\n\n\nclass BertSelfOutput(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.hidden_size)\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n    def forward(self, hidden_states, input_tensor):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.dropout(hidden_states)\n        hidden_states = self.LayerNorm(hidden_states + input_tensor)\n        return hidden_states\n\n\nclass BertAttention(nn.Module):\n    def __init__(self, config, is_cross_attention=False):\n        super().__init__()\n        self.self = BertSelfAttention(config, is_cross_attention)\n        self.output = BertSelfOutput(config)\n        self.pruned_heads = set()\n\n    def prune_heads(self, heads):\n        if len(heads) == 0:\n            return\n        heads, index = find_pruneable_heads_and_indices(\n            heads, self.self.num_attention_heads, self.self.attention_head_size, self.pruned_heads\n        )\n\n        # Prune linear layers\n        self.self.query = prune_linear_layer(self.self.query, index)\n        self.self.key = prune_linear_layer(self.self.key, index)\n        self.self.value = prune_linear_layer(self.self.value, index)\n        self.output.dense = prune_linear_layer(self.output.dense, index, dim=1)\n\n        # Update hyper params and store pruned heads\n        self.self.num_attention_heads = self.self.num_attention_heads - len(heads)\n        self.self.all_head_size = self.self.attention_head_size * self.self.num_attention_heads\n        self.pruned_heads = self.pruned_heads.union(heads)\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_value=None,\n        output_attentions=False,\n    ):\n        self_outputs = self.self(\n            hidden_states,\n            attention_mask,\n            head_mask,\n            encoder_hidden_states,\n            encoder_attention_mask,\n            past_key_value,\n            output_attentions,\n        )\n        attention_output = self.output(self_outputs[0], hidden_states)\n        outputs = (attention_output,) + self_outputs[1:]  # add attentions if we output them\n        return outputs\n\n\nclass BertIntermediate(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.intermediate_size)\n        if isinstance(config.hidden_act, str):\n            self.intermediate_act_fn = ACT2FN[config.hidden_act]\n        else:\n            self.intermediate_act_fn = config.hidden_act\n\n    def forward(self, hidden_states):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.intermediate_act_fn(hidden_states)\n        return hidden_states\n\n\nclass BertOutput(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.intermediate_size, config.hidden_size)\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n    def forward(self, hidden_states, input_tensor):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.dropout(hidden_states)\n        hidden_states = self.LayerNorm(hidden_states + input_tensor)\n        return hidden_states\n\n\nclass BertLayer(nn.Module):\n    def __init__(self, config, layer_num):\n        super().__init__()\n        self.config = config\n        self.chunk_size_feed_forward = config.chunk_size_feed_forward\n        self.seq_len_dim = 1\n        self.attention = BertAttention(config)      \n        self.layer_num = layer_num          \n        if self.config.add_cross_attention:\n            self.crossattention = BertAttention(config, is_cross_attention=self.config.add_cross_attention)\n        self.intermediate = BertIntermediate(config)\n        self.output = BertOutput(config)\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_value=None,\n        output_attentions=False,\n        mode=None,\n    ):\n        \n        if mode == 'tagging':\n            \n            assert encoder_hidden_states is not None, \"encoder_hidden_states must be given for cross-attention layers\"\n\n            cross_attention_outputs = self.crossattention(\n                hidden_states,\n                attention_mask,\n                head_mask,\n                encoder_hidden_states,\n                encoder_attention_mask,\n                output_attentions=output_attentions,\n            )\n            attention_output = cross_attention_outputs[0]\n            outputs = cross_attention_outputs[1:-1]  # add cross attentions if we output attention weights  \n\n            present_key_value = cross_attention_outputs[-1]\n\n        else:\n            # decoder uni-directional self-attention cached key/values tuple is at positions 1,2\n            self_attn_past_key_value = past_key_value[:2] if past_key_value is not None else None\n            self_attention_outputs = self.attention(\n                hidden_states,\n                attention_mask,\n                head_mask,\n                output_attentions=output_attentions,\n                past_key_value=self_attn_past_key_value,\n            )\n            attention_output = self_attention_outputs[0]\n\n            outputs = self_attention_outputs[1:-1]\n            present_key_value = self_attention_outputs[-1]\n\n            if mode=='multimodal':\n                assert encoder_hidden_states is not None, \"encoder_hidden_states must be given for cross-attention layers\"\n\n                cross_attention_outputs = self.crossattention(\n                    attention_output,\n                    attention_mask,\n                    head_mask,\n                    encoder_hidden_states,\n                    encoder_attention_mask,\n                    output_attentions=output_attentions,\n                )\n                attention_output = cross_attention_outputs[0]\n                outputs = outputs + cross_attention_outputs[1:-1]  # add cross attentions if we output attention weights                               \n        layer_output = apply_chunking_to_forward(\n            self.feed_forward_chunk, self.chunk_size_feed_forward, self.seq_len_dim, attention_output\n        )\n        outputs = (layer_output,) + outputs\n\n        outputs = outputs + (present_key_value,)\n\n        return outputs\n\n    def feed_forward_chunk(self, attention_output):\n        intermediate_output = self.intermediate(attention_output)\n        layer_output = self.output(intermediate_output, attention_output)\n        return layer_output\n\n\nclass BertEncoder(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.config = config\n        self.layer = nn.ModuleList([BertLayer(config,i) for i in range(config.num_hidden_layers)])\n        self.gradient_checkpointing = False\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_values=None,\n        use_cache=None,\n        output_attentions=False,\n        output_hidden_states=False,\n        return_dict=True,\n        mode='multimodal',\n    ):\n        all_hidden_states = () if output_hidden_states else None\n        all_self_attentions = () if output_attentions else None\n        all_cross_attentions = () if output_attentions and self.config.add_cross_attention else None\n\n        next_decoder_cache = () if use_cache else None\n               \n        for i in range(self.config.num_hidden_layers):\n            layer_module = self.layer[i]\n            if output_hidden_states:\n                all_hidden_states = all_hidden_states + (hidden_states,)\n\n            layer_head_mask = head_mask[i] if head_mask is not None else None\n            past_key_value = past_key_values[i] if past_key_values is not None else None\n\n            if self.gradient_checkpointing and self.training:\n\n                if use_cache:\n                    logger.warn(\n                        \"`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`...\"\n                    )\n                    use_cache = False\n\n                def create_custom_forward(module):\n                    def custom_forward(*inputs):\n                        return module(*inputs, past_key_value, output_attentions)\n\n                    return custom_forward\n\n                layer_outputs = torch.utils.checkpoint.checkpoint(\n                    create_custom_forward(layer_module),\n                    hidden_states,\n                    attention_mask,\n                    layer_head_mask,\n                    encoder_hidden_states,\n                    encoder_attention_mask,\n                    mode=mode,\n                )\n            else:\n                layer_outputs = layer_module(\n                    hidden_states,\n                    attention_mask,\n                    layer_head_mask,\n                    encoder_hidden_states,\n                    encoder_attention_mask,\n                    past_key_value,\n                    output_attentions,\n                    mode=mode,\n                )\n\n            hidden_states = layer_outputs[0]\n            if use_cache:\n                next_decoder_cache += (layer_outputs[-1],)\n            if output_attentions:\n                all_self_attentions = all_self_attentions + (layer_outputs[1],)\n\n        if output_hidden_states:\n            all_hidden_states = all_hidden_states + (hidden_states,)\n\n        if not return_dict:\n            return tuple(\n                v\n                for v in [\n                    hidden_states,\n                    next_decoder_cache,\n                    all_hidden_states,\n                    all_self_attentions,\n                    all_cross_attentions,\n                ]\n                if v is not None\n            )\n        return BaseModelOutputWithPastAndCrossAttentions(\n            last_hidden_state=hidden_states,\n            past_key_values=next_decoder_cache,\n            hidden_states=all_hidden_states,\n            attentions=all_self_attentions,\n            cross_attentions=all_cross_attentions,\n        )\n\n\nclass BertPooler(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.hidden_size)\n        self.activation = nn.Tanh()\n\n    def forward(self, hidden_states):\n        # We \"pool\" the model by simply taking the hidden state corresponding\n        # to the first token.\n        first_token_tensor = hidden_states[:, 0]\n        pooled_output = self.dense(first_token_tensor)\n        pooled_output = self.activation(pooled_output)\n        return pooled_output\n\n\nclass BertPredictionHeadTransform(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.hidden_size)\n        if isinstance(config.hidden_act, str):\n            self.transform_act_fn = ACT2FN[config.hidden_act]\n        else:\n            self.transform_act_fn = config.hidden_act\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n\n    def forward(self, hidden_states):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.transform_act_fn(hidden_states)\n        hidden_states = self.LayerNorm(hidden_states)\n        return hidden_states\n\n\nclass BertLMPredictionHead(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.transform = BertPredictionHeadTransform(config)\n\n        # The output weights are the same as the input embeddings, but there is\n        # an output-only bias for each token.\n        self.decoder = nn.Linear(config.hidden_size, config.vocab_size, bias=False)\n\n        self.bias = nn.Parameter(torch.zeros(config.vocab_size))\n\n        # Need a link between the two variables so that the bias is correctly resized with `resize_token_embeddings`\n        self.decoder.bias = self.bias\n\n    def forward(self, hidden_states):\n        hidden_states = self.transform(hidden_states)\n        hidden_states = self.decoder(hidden_states)\n        return hidden_states\n\n\nclass BertOnlyMLMHead(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.predictions = BertLMPredictionHead(config)\n\n    def forward(self, sequence_output):\n        prediction_scores = self.predictions(sequence_output)\n        return prediction_scores\n\n\nclass BertPreTrainedModel(PreTrainedModel):\n    \"\"\"\n    An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained\n    models.\n    \"\"\"\n\n    config_class = BertConfig\n    base_model_prefix = \"bert\"\n    _keys_to_ignore_on_load_missing = [r\"position_ids\"]\n\n    def _init_weights(self, module):\n        \"\"\" Initialize the weights \"\"\"\n        if isinstance(module, (nn.Linear, nn.Embedding)):\n            # Slightly different from the TF version which uses truncated_normal for initialization\n            # cf https://github.com/pytorch/pytorch/pull/5617\n            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)\n        elif isinstance(module, nn.LayerNorm):\n            module.bias.data.zero_()\n            module.weight.data.fill_(1.0)\n        if isinstance(module, nn.Linear) and module.bias is not None:\n            module.bias.data.zero_()\n\n\nclass BertModel(BertPreTrainedModel):\n    \"\"\"\n    The model can behave as an encoder (with only self-attention) as well as a decoder, in which case a layer of\n    cross-attention is added between the self-attention layers, following the architecture described in `Attention is\n    all you need <https://arxiv.org/abs/1706.03762>`__ by Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit,\n    Llion Jones, Aidan N. Gomez, Lukasz Kaiser and Illia Polosukhin.\n    argument and :obj:`add_cross_attention` set to :obj:`True`; an :obj:`encoder_hidden_states` is then expected as an\n    input to the forward pass.\n    \"\"\"\n\n    def __init__(self, config, add_pooling_layer=True):\n        super().__init__(config)\n        self.config = config\n\n        self.embeddings = BertEmbeddings(config)\n        \n        self.encoder = BertEncoder(config)\n\n        self.pooler = BertPooler(config) if add_pooling_layer else None\n\n        self.init_weights()\n \n\n    def get_input_embeddings(self):\n        return self.embeddings.word_embeddings\n\n    def set_input_embeddings(self, value):\n        self.embeddings.word_embeddings = value\n\n    def _prune_heads(self, heads_to_prune):\n        \"\"\"\n        Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer} See base\n        class PreTrainedModel\n        \"\"\"\n        for layer, heads in heads_to_prune.items():\n            self.encoder.layer[layer].attention.prune_heads(heads)\n\n    \n    def get_extended_attention_mask(self, attention_mask: Tensor, input_shape: Tuple[int], device: device, is_decoder: bool) -> Tensor:\n        \"\"\"\n        Makes broadcastable attention and causal masks so that future and masked tokens are ignored.\n\n        Arguments:\n            attention_mask (:obj:`torch.Tensor`):\n                Mask with ones indicating tokens to attend to, zeros for tokens to ignore.\n            input_shape (:obj:`Tuple[int]`):\n                The shape of the input to the model.\n            device: (:obj:`torch.device`):\n                The device of the input to the model.\n\n        Returns:\n            :obj:`torch.Tensor` The extended attention mask, with a the same dtype as :obj:`attention_mask.dtype`.\n        \"\"\"\n        # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length]\n        # ourselves in which case we just need to make it broadcastable to all heads.\n        if attention_mask.dim() == 3:\n            extended_attention_mask = attention_mask[:, None, :, :]\n        elif attention_mask.dim() == 2:\n            # Provided a padding mask of dimensions [batch_size, seq_length]\n            # - if the model is a decoder, apply a causal mask in addition to the padding mask\n            # - if the model is an encoder, make the mask broadcastable to [batch_size, num_heads, seq_length, seq_length]\n            if is_decoder:\n                batch_size, seq_length = input_shape\n\n                seq_ids = torch.arange(seq_length, device=device)\n                causal_mask = seq_ids[None, None, :].repeat(batch_size, seq_length, 1) <= seq_ids[None, :, None]\n                # in case past_key_values are used we need to add a prefix ones mask to the causal mask\n                # causal and attention masks must have same type with pytorch version < 1.3\n                causal_mask = causal_mask.to(attention_mask.dtype)\n   \n                if causal_mask.shape[1] < attention_mask.shape[1]:\n                    prefix_seq_len = attention_mask.shape[1] - causal_mask.shape[1]\n                    causal_mask = torch.cat(\n                        [\n                            torch.ones((batch_size, seq_length, prefix_seq_len), device=device, dtype=causal_mask.dtype),\n                            causal_mask,\n                        ],\n                        axis=-1,\n                    )                     \n\n                extended_attention_mask = causal_mask[:, None, :, :] * attention_mask[:, None, None, :]\n            else:\n                extended_attention_mask = attention_mask[:, None, None, :]\n        else:\n            raise ValueError(\n                \"Wrong shape for input_ids (shape {}) or attention_mask (shape {})\".format(\n                    input_shape, attention_mask.shape\n                )\n            )\n\n        # Since attention_mask is 1.0 for positions we want to attend and 0.0 for\n        # masked positions, this operation will create a tensor which is 0.0 for\n        # positions we want to attend and -10000.0 for masked positions.\n        # Since we are adding it to the raw scores before the softmax, this is\n        # effectively the same as removing these entirely.\n        extended_attention_mask = extended_attention_mask.to(dtype=self.dtype)  # fp16 compatibility\n        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0\n        return extended_attention_mask\n    \n    def forward(\n        self,\n        input_ids=None,\n        attention_mask=None,\n        position_ids=None,\n        head_mask=None,\n        inputs_embeds=None,\n        encoder_embeds=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_values=None,\n        use_cache=None,\n        output_attentions=None,\n        output_hidden_states=None,\n        return_dict=None,\n        is_decoder=False,\n        mode='multimodal',\n    ):\n        r\"\"\"\n        encoder_hidden_states  (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`):\n            Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention if\n            the model is configured as a decoder.\n        encoder_attention_mask (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`):\n            Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used in\n            the cross-attention if the model is configured as a decoder. Mask values selected in ``[0, 1]``:\n            - 1 for tokens that are **not masked**,\n            - 0 for tokens that are **masked**.\n        past_key_values (:obj:`tuple(tuple(torch.FloatTensor))` of length :obj:`config.n_layers` with each tuple having 4 tensors of shape :obj:`(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`):\n            Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up decoding.\n            If :obj:`past_key_values` are used, the user can optionally input only the last :obj:`decoder_input_ids`\n            (those that don't have their past key value states given to this model) of shape :obj:`(batch_size, 1)`\n            instead of all :obj:`decoder_input_ids` of shape :obj:`(batch_size, sequence_length)`.\n        use_cache (:obj:`bool`, `optional`):\n            If set to :obj:`True`, :obj:`past_key_values` key value states are returned and can be used to speed up\n            decoding (see :obj:`past_key_values`).\n        \"\"\"\n        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions\n        output_hidden_states = (\n            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states\n        )\n        return_dict = return_dict if return_dict is not None else self.config.use_return_dict\n\n        if is_decoder:\n            use_cache = use_cache if use_cache is not None else self.config.use_cache\n        else:\n            use_cache = False\n\n        if input_ids is not None and inputs_embeds is not None:\n            raise ValueError(\"You cannot specify both input_ids and inputs_embeds at the same time\")\n        elif input_ids is not None:\n            input_shape = input_ids.size()\n            batch_size, seq_length = input_shape\n            device = input_ids.device\n        elif inputs_embeds is not None:\n            input_shape = inputs_embeds.size()[:-1]\n            batch_size, seq_length = input_shape\n            device = inputs_embeds.device\n        elif encoder_embeds is not None:    \n            input_shape = encoder_embeds.size()[:-1]\n            batch_size, seq_length = input_shape \n            device = encoder_embeds.device\n        else:\n            raise ValueError(\"You have to specify either input_ids or inputs_embeds or encoder_embeds\")\n\n        # past_key_values_length\n        past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0\n\n        if attention_mask is None:\n            attention_mask = torch.ones(((batch_size, seq_length + past_key_values_length)), device=device)\n            \n        # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length]\n        # ourselves in which case we just need to make it broadcastable to all heads.\n        extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, input_shape, \n                                                                                 device, is_decoder)\n\n        # If a 2D or 3D attention mask is provided for the cross-attention\n        # we need to make broadcastable to [batch_size, num_heads, seq_length, seq_length]\n        if encoder_hidden_states is not None:\n            if type(encoder_hidden_states) == list:\n                encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states[0].size()\n            else:\n                encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states.size()\n            encoder_hidden_shape = (encoder_batch_size, encoder_sequence_length)\n            \n            if type(encoder_attention_mask) == list:\n                encoder_extended_attention_mask = [self.invert_attention_mask(mask) for mask in encoder_attention_mask]\n            elif encoder_attention_mask is None:\n                encoder_attention_mask = torch.ones(encoder_hidden_shape, device=device)\n                encoder_extended_attention_mask = self.invert_attention_mask(encoder_attention_mask)\n            else:    \n                encoder_extended_attention_mask = self.invert_attention_mask(encoder_attention_mask)\n        else:\n            encoder_extended_attention_mask = None\n\n        # Prepare head mask if needed\n        # 1.0 in head_mask indicate we keep the head\n        # attention_probs has shape bsz x n_heads x N x N\n        # input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]\n        # and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]\n        head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers)\n        \n        if encoder_embeds is None:\n            embedding_output = self.embeddings(\n                input_ids=input_ids,\n                position_ids=position_ids,\n                inputs_embeds=inputs_embeds,\n                past_key_values_length=past_key_values_length,\n            )\n        else:\n            embedding_output = encoder_embeds\n            \n        encoder_outputs = self.encoder(\n            embedding_output,\n            attention_mask=extended_attention_mask,\n            head_mask=head_mask,\n            encoder_hidden_states=encoder_hidden_states,\n            encoder_attention_mask=encoder_extended_attention_mask,\n            past_key_values=past_key_values,\n            use_cache=use_cache,\n            output_attentions=output_attentions,\n            output_hidden_states=output_hidden_states,\n            return_dict=return_dict,\n            mode=mode,\n        )\n        sequence_output = encoder_outputs[0]\n        pooled_output = self.pooler(sequence_output) if self.pooler is not None else None\n\n        if not return_dict:\n            return (sequence_output, pooled_output) + encoder_outputs[1:]\n\n        return BaseModelOutputWithPoolingAndCrossAttentions(\n            last_hidden_state=sequence_output,\n            pooler_output=pooled_output,\n            past_key_values=encoder_outputs.past_key_values,\n            hidden_states=encoder_outputs.hidden_states,\n            attentions=encoder_outputs.attentions,\n            cross_attentions=encoder_outputs.cross_attentions,\n        )\n\n\nclass BertLMHeadModel(BertPreTrainedModel):\n\n    _keys_to_ignore_on_load_unexpected = [r\"pooler\"]\n    _keys_to_ignore_on_load_missing = [r\"position_ids\", r\"predictions.decoder.bias\"]\n\n    def __init__(self, config):\n        super().__init__(config)\n\n        self.bert = BertModel(config, add_pooling_layer=False)\n        self.cls = BertOnlyMLMHead(config)\n\n        self.init_weights()\n\n    def get_output_embeddings(self):\n        return self.cls.predictions.decoder\n\n    def set_output_embeddings(self, new_embeddings):\n        self.cls.predictions.decoder = new_embeddings\n\n    def forward(\n        self,\n        input_ids=None,\n        attention_mask=None,\n        position_ids=None,\n        head_mask=None,\n        inputs_embeds=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        labels=None,\n        past_key_values=None,\n        use_cache=None,\n        output_attentions=None,\n        output_hidden_states=None,\n        return_dict=None,\n        return_logits=False,            \n        is_decoder=True,\n        reduction='mean',\n        mode='multimodal', \n    ):\n        r\"\"\"\n        encoder_hidden_states  (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`):\n            Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention if\n            the model is configured as a decoder.\n        encoder_attention_mask (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`):\n            Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used in\n            the cross-attention if the model is configured as a decoder. Mask values selected in ``[0, 1]``:\n            - 1 for tokens that are **not masked**,\n            - 0 for tokens that are **masked**.\n        labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`):\n            Labels for computing the left-to-right language modeling loss (next word prediction). Indices should be in\n            ``[-100, 0, ..., config.vocab_size]`` (see ``input_ids`` docstring) Tokens with indices set to ``-100`` are\n            ignored (masked), the loss is only computed for the tokens with labels n ``[0, ..., config.vocab_size]``\n        past_key_values (:obj:`tuple(tuple(torch.FloatTensor))` of length :obj:`config.n_layers` with each tuple having 4 tensors of shape :obj:`(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`):\n            Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up decoding.\n            If :obj:`past_key_values` are used, the user can optionally input only the last :obj:`decoder_input_ids`\n            (those that don't have their past key value states given to this model) of shape :obj:`(batch_size, 1)`\n            instead of all :obj:`decoder_input_ids` of shape :obj:`(batch_size, sequence_length)`.\n        use_cache (:obj:`bool`, `optional`):\n            If set to :obj:`True`, :obj:`past_key_values` key value states are returned and can be used to speed up\n            decoding (see :obj:`past_key_values`).\n        Returns:\n        Example::\n            >>> from transformers import BertTokenizer, BertLMHeadModel, BertConfig\n            >>> import torch\n            >>> tokenizer = BertTokenizer.from_pretrained('bert-base-cased')\n            >>> config = BertConfig.from_pretrained(\"bert-base-cased\")\n            >>> model = BertLMHeadModel.from_pretrained('bert-base-cased', config=config)\n            >>> inputs = tokenizer(\"Hello, my dog is cute\", return_tensors=\"pt\")\n            >>> outputs = model(**inputs)\n            >>> prediction_logits = outputs.logits\n        \"\"\"\n        return_dict = return_dict if return_dict is not None else self.config.use_return_dict\n        if labels is not None:\n            use_cache = False\n\n        outputs = self.bert(\n            input_ids,\n            attention_mask=attention_mask,\n            position_ids=position_ids,\n            head_mask=head_mask,\n            inputs_embeds=inputs_embeds,\n            encoder_hidden_states=encoder_hidden_states,\n            encoder_attention_mask=encoder_attention_mask,\n            past_key_values=past_key_values,\n            use_cache=use_cache,\n            output_attentions=output_attentions,\n            output_hidden_states=output_hidden_states,\n            return_dict=return_dict,\n            is_decoder=is_decoder,\n            mode=mode,\n        )\n        \n        sequence_output = outputs[0]\n        prediction_scores = self.cls(sequence_output)\n        # sequence_output.shape torch.Size([85, 30, 768])\n        # prediction_scores.shape torch.Size([85, 30, 30524])\n        # labels.shape torch.Size([85, 30])\n\n\n        if return_logits:\n            return prediction_scores[:, :-1, :].contiguous()  \n\n        lm_loss = None\n        if labels is not None:\n            # we are doing next-token prediction; shift prediction scores and input ids by one\n            shifted_prediction_scores = prediction_scores[:, :-1, :].contiguous()\n            labels = labels[:, 1:].contiguous()\n            loss_fct = CrossEntropyLoss(reduction=reduction, label_smoothing=0.1) \n            lm_loss = loss_fct(shifted_prediction_scores.view(-1, self.config.vocab_size), labels.view(-1))\n            if reduction=='none':\n                lm_loss = lm_loss.view(prediction_scores.size(0),-1).sum(1)               \n\n        if not return_dict:\n            output = (prediction_scores,) + outputs[2:]\n            return ((lm_loss,) + output) if lm_loss is not None else output\n\n        return CausalLMOutputWithCrossAttentions(\n            loss=lm_loss,\n            logits=prediction_scores,\n            past_key_values=outputs.past_key_values,\n            hidden_states=outputs.hidden_states,\n            attentions=outputs.attentions,\n            cross_attentions=outputs.cross_attentions,\n        )\n\n    def prepare_inputs_for_generation(self, input_ids, past=None, attention_mask=None, **model_kwargs):\n        input_shape = input_ids.shape\n        # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly\n        if attention_mask is None:\n            attention_mask = input_ids.new_ones(input_shape)\n\n        # cut decoder_input_ids if past is used\n        if past is not None:\n            input_ids = input_ids[:, -1:]\n\n        return {\n            \"input_ids\": input_ids, \n            \"attention_mask\": attention_mask, \n            \"past_key_values\": past,\n            \"encoder_hidden_states\": model_kwargs.get(\"encoder_hidden_states\", None),\n            \"encoder_attention_mask\": model_kwargs.get(\"encoder_attention_mask\", None),\n            \"is_decoder\": True,\n        }\n\n    def _reorder_cache(self, past, beam_idx):\n        reordered_past = ()\n        for layer_past in past:\n            reordered_past += (tuple(past_state.index_select(0, beam_idx) for past_state in layer_past),)\n        return reordered_past\n\n\n"
  },
  {
    "path": "ram/models/bert_lora.py",
    "content": "'''\n * Copyright (c) 2022, salesforce.com, inc.\n * All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause\n * By Junnan Li\n * Based on huggingface code base\n * https://github.com/huggingface/transformers/blob/v4.15.0/src/transformers/models/bert\n'''\n\nimport math\nimport os\nimport warnings\nfrom dataclasses import dataclass\nfrom typing import Optional, Tuple\n\nimport torch\nfrom torch import Tensor, device, dtype, nn\nimport torch.utils.checkpoint\nfrom torch import nn\nfrom torch.nn import CrossEntropyLoss\nimport torch.nn.functional as F\n\nfrom transformers.activations import ACT2FN\nfrom transformers.file_utils import (\n    ModelOutput,\n)\nfrom transformers.modeling_outputs import (\n    BaseModelOutputWithPastAndCrossAttentions,\n    BaseModelOutputWithPoolingAndCrossAttentions,\n    CausalLMOutputWithCrossAttentions,\n    MaskedLMOutput,\n    MultipleChoiceModelOutput,\n    NextSentencePredictorOutput,\n    QuestionAnsweringModelOutput,\n    SequenceClassifierOutput,\n    TokenClassifierOutput,\n)\nfrom transformers.modeling_utils import (\n    PreTrainedModel,\n    apply_chunking_to_forward,\n    find_pruneable_heads_and_indices,\n    prune_linear_layer,\n)\nfrom transformers.utils import logging\nfrom transformers.models.bert.configuration_bert import BertConfig\n\nimport loralib as lora\n\n\nlogger = logging.get_logger(__name__)\n\n\nclass BertEmbeddings_nopos(nn.Module):\n    \"\"\"Construct the embeddings from word and position embeddings.\"\"\"\n\n    def __init__(self, config):\n        super().__init__()\n        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)\n        # self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)\n\n        # self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load\n        # any TensorFlow checkpoint file\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n        # position_ids (1, len position emb) is contiguous in memory and exported when serialized\n        # self.register_buffer(\"position_ids\", torch.arange(config.max_position_embeddings).expand((1, -1)))\n        # self.position_embedding_type = getattr(config, \"position_embedding_type\", \"absolute\")\n        \n        self.config = config\n\n    def forward(\n        self, input_ids=None, position_ids=None, inputs_embeds=None, past_key_values_length=0\n    ):\n        if input_ids is not None:\n            input_shape = input_ids.size()\n        else:\n            input_shape = inputs_embeds.size()[:-1]\n\n        seq_length = input_shape[1]\n\n        # if position_ids is None:\n            # position_ids = self.position_ids[:, past_key_values_length : seq_length + past_key_values_length]\n\n        if inputs_embeds is None:\n            inputs_embeds = self.word_embeddings(input_ids)\n\n        embeddings = inputs_embeds\n\n        # if self.position_embedding_type == \"absolute\":\n        #     position_embeddings = self.position_embeddings(position_ids)\n        #     # print('add position_embeddings!!!!')\n        #     embeddings += position_embeddings\n        embeddings = self.LayerNorm(embeddings)\n        embeddings = self.dropout(embeddings)\n        return embeddings\n\n\n\n\nclass BertEmbeddings(nn.Module):\n    \"\"\"Construct the embeddings from word and position embeddings.\"\"\"\n\n    def __init__(self, config):\n        super().__init__()\n        self.word_embeddings = nn.Embedding(config.vocab_size, config.hidden_size, padding_idx=config.pad_token_id)\n        self.position_embeddings = nn.Embedding(config.max_position_embeddings, config.hidden_size)\n\n        # self.LayerNorm is not snake-cased to stick with TensorFlow model variable name and be able to load\n        # any TensorFlow checkpoint file\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n        # position_ids (1, len position emb) is contiguous in memory and exported when serialized\n        self.register_buffer(\"position_ids\", torch.arange(config.max_position_embeddings).expand((1, -1)))\n        self.position_embedding_type = getattr(config, \"position_embedding_type\", \"absolute\")\n        \n        self.config = config\n\n    def forward(\n        self, input_ids=None, position_ids=None, inputs_embeds=None, past_key_values_length=0\n    ):\n        if input_ids is not None:\n            input_shape = input_ids.size()\n        else:\n            input_shape = inputs_embeds.size()[:-1]\n\n        seq_length = input_shape[1]\n\n        if position_ids is None:\n            position_ids = self.position_ids[:, past_key_values_length : seq_length + past_key_values_length]\n\n        if inputs_embeds is None:\n            inputs_embeds = self.word_embeddings(input_ids)\n\n        embeddings = inputs_embeds\n\n        if self.position_embedding_type == \"absolute\":\n            position_embeddings = self.position_embeddings(position_ids)\n            # print('add position_embeddings!!!!')\n            embeddings += position_embeddings\n        embeddings = self.LayerNorm(embeddings)\n        embeddings = self.dropout(embeddings)\n        return embeddings\n\n\nclass BertSelfAttention(nn.Module):\n    def __init__(self, config, is_cross_attention):\n        super().__init__()\n        self.config = config\n        if config.hidden_size % config.num_attention_heads != 0 and not hasattr(config, \"embedding_size\"):\n            raise ValueError(\n                \"The hidden size (%d) is not a multiple of the number of attention \"\n                \"heads (%d)\" % (config.hidden_size, config.num_attention_heads)\n            )\n        \n        self.num_attention_heads = config.num_attention_heads\n        self.attention_head_size = int(config.hidden_size / config.num_attention_heads)\n        self.all_head_size = self.num_attention_heads * self.attention_head_size\n\n        # self.query = nn.Linear(config.hidden_size, self.all_head_size)\n        self.query = lora.Linear(config.hidden_size, self.all_head_size, r=8)\n        if is_cross_attention:\n            # self.key = nn.Linear(config.encoder_width, self.all_head_size)\n            self.key = lora.Linear(config.encoder_width, self.all_head_size, r=8)\n            self.value = nn.Linear(config.encoder_width, self.all_head_size)\n        else:\n            # self.key = nn.Linear(config.hidden_size, self.all_head_size)\n            self.key = lora.Linear(config.hidden_size, self.all_head_size, r=8)\n            self.value = nn.Linear(config.hidden_size, self.all_head_size)\n\n        self.dropout = nn.Dropout(config.attention_probs_dropout_prob)\n        self.position_embedding_type = getattr(config, \"position_embedding_type\", \"absolute\")\n        if self.position_embedding_type == \"relative_key\" or self.position_embedding_type == \"relative_key_query\":\n            self.max_position_embeddings = config.max_position_embeddings\n            self.distance_embedding = nn.Embedding(2 * config.max_position_embeddings - 1, self.attention_head_size)\n        self.save_attention = False   \n            \n    def save_attn_gradients(self, attn_gradients):\n        self.attn_gradients = attn_gradients\n        \n    def get_attn_gradients(self):\n        return self.attn_gradients\n    \n    def save_attention_map(self, attention_map):\n        self.attention_map = attention_map\n        \n    def get_attention_map(self):\n        return self.attention_map\n    \n    def transpose_for_scores(self, x):\n        new_x_shape = x.size()[:-1] + (self.num_attention_heads, self.attention_head_size)\n        x = x.view(*new_x_shape)\n        return x.permute(0, 2, 1, 3)\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_value=None,\n        output_attentions=False,\n    ):\n        mixed_query_layer = self.query(hidden_states)\n\n        # If this is instantiated as a cross-attention module, the keys\n        # and values come from an encoder; the attention mask needs to be\n        # such that the encoder's padding tokens are not attended to.\n        is_cross_attention = encoder_hidden_states is not None\n\n        if is_cross_attention:\n            # print(self.key.weight.shape)\n            key_layer = self.transpose_for_scores(self.key(encoder_hidden_states))\n            value_layer = self.transpose_for_scores(self.value(encoder_hidden_states))\n            attention_mask = encoder_attention_mask\n        elif past_key_value is not None:\n            key_layer = self.transpose_for_scores(self.key(hidden_states))\n            value_layer = self.transpose_for_scores(self.value(hidden_states))\n            key_layer = torch.cat([past_key_value[0], key_layer], dim=2)\n            value_layer = torch.cat([past_key_value[1], value_layer], dim=2)\n        else:\n            key_layer = self.transpose_for_scores(self.key(hidden_states))\n            value_layer = self.transpose_for_scores(self.value(hidden_states))\n\n        query_layer = self.transpose_for_scores(mixed_query_layer)\n\n        past_key_value = (key_layer, value_layer)\n\n        # compatible with higher versions of transformers \n        if key_layer.shape[0] > query_layer.shape[0]:\n            key_layer = key_layer[:query_layer.shape[0], :, :, :]\n            attention_mask = attention_mask[:query_layer.shape[0], :, :]\n            value_layer = value_layer[:query_layer.shape[0], :, :, :]\n\n        # Take the dot product between \"query\" and \"key\" to get the raw attention scores.\n        attention_scores = torch.matmul(query_layer, key_layer.transpose(-1, -2))\n\n        if self.position_embedding_type == \"relative_key\" or self.position_embedding_type == \"relative_key_query\":\n            seq_length = hidden_states.size()[1]\n            position_ids_l = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(-1, 1)\n            position_ids_r = torch.arange(seq_length, dtype=torch.long, device=hidden_states.device).view(1, -1)\n            distance = position_ids_l - position_ids_r\n            positional_embedding = self.distance_embedding(distance + self.max_position_embeddings - 1)\n            positional_embedding = positional_embedding.to(dtype=query_layer.dtype)  # fp16 compatibility\n\n            if self.position_embedding_type == \"relative_key\":\n                relative_position_scores = torch.einsum(\"bhld,lrd->bhlr\", query_layer, positional_embedding)\n                attention_scores = attention_scores + relative_position_scores\n            elif self.position_embedding_type == \"relative_key_query\":\n                relative_position_scores_query = torch.einsum(\"bhld,lrd->bhlr\", query_layer, positional_embedding)\n                relative_position_scores_key = torch.einsum(\"bhrd,lrd->bhlr\", key_layer, positional_embedding)\n                attention_scores = attention_scores + relative_position_scores_query + relative_position_scores_key\n\n        attention_scores = attention_scores / math.sqrt(self.attention_head_size)\n        if attention_mask is not None:\n            # Apply the attention mask is (precomputed for all layers in BertModel forward() function)\n            attention_scores = attention_scores + attention_mask\n\n        # Normalize the attention scores to probabilities.\n        attention_probs = nn.Softmax(dim=-1)(attention_scores)\n        \n        if is_cross_attention and self.save_attention:\n            self.save_attention_map(attention_probs)\n            attention_probs.register_hook(self.save_attn_gradients)         \n\n        # This is actually dropping out entire tokens to attend to, which might\n        # seem a bit unusual, but is taken from the original Transformer paper.\n        attention_probs_dropped = self.dropout(attention_probs)\n\n        # Mask heads if we want to\n        if head_mask is not None:\n            attention_probs_dropped = attention_probs_dropped * head_mask\n\n        context_layer = torch.matmul(attention_probs_dropped, value_layer)\n\n        context_layer = context_layer.permute(0, 2, 1, 3).contiguous()\n        new_context_layer_shape = context_layer.size()[:-2] + (self.all_head_size,)\n        context_layer = context_layer.view(*new_context_layer_shape)\n\n        outputs = (context_layer, attention_probs) if output_attentions else (context_layer,)\n\n        outputs = outputs + (past_key_value,)\n        return outputs\n\n\nclass BertSelfOutput(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.hidden_size)\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n    def forward(self, hidden_states, input_tensor):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.dropout(hidden_states)\n        hidden_states = self.LayerNorm(hidden_states + input_tensor)\n        return hidden_states\n\n\nclass BertAttention(nn.Module):\n    def __init__(self, config, is_cross_attention=False):\n        super().__init__()\n        self.self = BertSelfAttention(config, is_cross_attention)\n        self.output = BertSelfOutput(config)\n        self.pruned_heads = set()\n\n    def prune_heads(self, heads):\n        if len(heads) == 0:\n            return\n        heads, index = find_pruneable_heads_and_indices(\n            heads, self.self.num_attention_heads, self.self.attention_head_size, self.pruned_heads\n        )\n\n        # Prune linear layers\n        self.self.query = prune_linear_layer(self.self.query, index)\n        self.self.key = prune_linear_layer(self.self.key, index)\n        self.self.value = prune_linear_layer(self.self.value, index)\n        self.output.dense = prune_linear_layer(self.output.dense, index, dim=1)\n\n        # Update hyper params and store pruned heads\n        self.self.num_attention_heads = self.self.num_attention_heads - len(heads)\n        self.self.all_head_size = self.self.attention_head_size * self.self.num_attention_heads\n        self.pruned_heads = self.pruned_heads.union(heads)\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_value=None,\n        output_attentions=False,\n    ):\n        self_outputs = self.self(\n            hidden_states,\n            attention_mask,\n            head_mask,\n            encoder_hidden_states,\n            encoder_attention_mask,\n            past_key_value,\n            output_attentions,\n        )\n        attention_output = self.output(self_outputs[0], hidden_states)\n        outputs = (attention_output,) + self_outputs[1:]  # add attentions if we output them\n        return outputs\n\n\nclass BertIntermediate(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.intermediate_size)\n        if isinstance(config.hidden_act, str):\n            self.intermediate_act_fn = ACT2FN[config.hidden_act]\n        else:\n            self.intermediate_act_fn = config.hidden_act\n\n    def forward(self, hidden_states):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.intermediate_act_fn(hidden_states)\n        return hidden_states\n\n\nclass BertOutput(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.intermediate_size, config.hidden_size)\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n        self.dropout = nn.Dropout(config.hidden_dropout_prob)\n\n    def forward(self, hidden_states, input_tensor):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.dropout(hidden_states)\n        hidden_states = self.LayerNorm(hidden_states + input_tensor)\n        return hidden_states\n\n\nclass BertLayer(nn.Module):\n    def __init__(self, config, layer_num):\n        super().__init__()\n        self.config = config\n        self.chunk_size_feed_forward = config.chunk_size_feed_forward\n        self.seq_len_dim = 1\n        self.attention = BertAttention(config)      \n        self.layer_num = layer_num          \n        if self.config.add_cross_attention:\n            self.crossattention = BertAttention(config, is_cross_attention=self.config.add_cross_attention)\n        self.intermediate = BertIntermediate(config)\n        self.output = BertOutput(config)\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_value=None,\n        output_attentions=False,\n        mode=None,\n    ):\n        \n        if mode == 'tagging':\n            \n            assert encoder_hidden_states is not None, \"encoder_hidden_states must be given for cross-attention layers\"\n\n            cross_attention_outputs = self.crossattention(\n                hidden_states,\n                attention_mask,\n                head_mask,\n                encoder_hidden_states,\n                encoder_attention_mask,\n                output_attentions=output_attentions,\n            )\n            attention_output = cross_attention_outputs[0]\n            outputs = cross_attention_outputs[1:-1]  # add cross attentions if we output attention weights  \n\n            present_key_value = cross_attention_outputs[-1]\n\n        else:\n            # decoder uni-directional self-attention cached key/values tuple is at positions 1,2\n            self_attn_past_key_value = past_key_value[:2] if past_key_value is not None else None\n            self_attention_outputs = self.attention(\n                hidden_states,\n                attention_mask,\n                head_mask,\n                output_attentions=output_attentions,\n                past_key_value=self_attn_past_key_value,\n            )\n            attention_output = self_attention_outputs[0]\n\n            outputs = self_attention_outputs[1:-1]\n            present_key_value = self_attention_outputs[-1]\n\n            if mode=='multimodal':\n                assert encoder_hidden_states is not None, \"encoder_hidden_states must be given for cross-attention layers\"\n\n                cross_attention_outputs = self.crossattention(\n                    attention_output,\n                    attention_mask,\n                    head_mask,\n                    encoder_hidden_states,\n                    encoder_attention_mask,\n                    output_attentions=output_attentions,\n                )\n                attention_output = cross_attention_outputs[0]\n                outputs = outputs + cross_attention_outputs[1:-1]  # add cross attentions if we output attention weights                               \n        layer_output = apply_chunking_to_forward(\n            self.feed_forward_chunk, self.chunk_size_feed_forward, self.seq_len_dim, attention_output\n        )\n        outputs = (layer_output,) + outputs\n\n        outputs = outputs + (present_key_value,)\n\n        return outputs\n\n    def feed_forward_chunk(self, attention_output):\n        intermediate_output = self.intermediate(attention_output)\n        layer_output = self.output(intermediate_output, attention_output)\n        return layer_output\n\n\nclass BertEncoder(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.config = config\n        self.layer = nn.ModuleList([BertLayer(config,i) for i in range(config.num_hidden_layers)])\n        self.gradient_checkpointing = False\n\n    def forward(\n        self,\n        hidden_states,\n        attention_mask=None,\n        head_mask=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_values=None,\n        use_cache=None,\n        output_attentions=False,\n        output_hidden_states=False,\n        return_dict=True,\n        mode='multimodal',\n    ):\n        all_hidden_states = () if output_hidden_states else None\n        all_self_attentions = () if output_attentions else None\n        all_cross_attentions = () if output_attentions and self.config.add_cross_attention else None\n\n        next_decoder_cache = () if use_cache else None\n               \n        for i in range(self.config.num_hidden_layers):\n            layer_module = self.layer[i]\n            if output_hidden_states:\n                all_hidden_states = all_hidden_states + (hidden_states,)\n\n            layer_head_mask = head_mask[i] if head_mask is not None else None\n            past_key_value = past_key_values[i] if past_key_values is not None else None\n\n            if self.gradient_checkpointing and self.training:\n\n                if use_cache:\n                    logger.warn(\n                        \"`use_cache=True` is incompatible with gradient checkpointing. Setting `use_cache=False`...\"\n                    )\n                    use_cache = False\n\n                def create_custom_forward(module):\n                    def custom_forward(*inputs):\n                        return module(*inputs, past_key_value, output_attentions)\n\n                    return custom_forward\n\n                layer_outputs = torch.utils.checkpoint.checkpoint(\n                    create_custom_forward(layer_module),\n                    hidden_states,\n                    attention_mask,\n                    layer_head_mask,\n                    encoder_hidden_states,\n                    encoder_attention_mask,\n                    mode=mode,\n                )\n            else:\n                layer_outputs = layer_module(\n                    hidden_states,\n                    attention_mask,\n                    layer_head_mask,\n                    encoder_hidden_states,\n                    encoder_attention_mask,\n                    past_key_value,\n                    output_attentions,\n                    mode=mode,\n                )\n\n            hidden_states = layer_outputs[0]\n            if use_cache:\n                next_decoder_cache += (layer_outputs[-1],)\n            if output_attentions:\n                all_self_attentions = all_self_attentions + (layer_outputs[1],)\n\n        if output_hidden_states:\n            all_hidden_states = all_hidden_states + (hidden_states,)\n\n        if not return_dict:\n            return tuple(\n                v\n                for v in [\n                    hidden_states,\n                    next_decoder_cache,\n                    all_hidden_states,\n                    all_self_attentions,\n                    all_cross_attentions,\n                ]\n                if v is not None\n            )\n        return BaseModelOutputWithPastAndCrossAttentions(\n            last_hidden_state=hidden_states,\n            past_key_values=next_decoder_cache,\n            hidden_states=all_hidden_states,\n            attentions=all_self_attentions,\n            cross_attentions=all_cross_attentions,\n        )\n\n\nclass BertPooler(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.hidden_size)\n        self.activation = nn.Tanh()\n\n    def forward(self, hidden_states):\n        # We \"pool\" the model by simply taking the hidden state corresponding\n        # to the first token.\n        first_token_tensor = hidden_states[:, 0]\n        pooled_output = self.dense(first_token_tensor)\n        pooled_output = self.activation(pooled_output)\n        return pooled_output\n\n\nclass BertPredictionHeadTransform(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.dense = nn.Linear(config.hidden_size, config.hidden_size)\n        if isinstance(config.hidden_act, str):\n            self.transform_act_fn = ACT2FN[config.hidden_act]\n        else:\n            self.transform_act_fn = config.hidden_act\n        self.LayerNorm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)\n\n    def forward(self, hidden_states):\n        hidden_states = self.dense(hidden_states)\n        hidden_states = self.transform_act_fn(hidden_states)\n        hidden_states = self.LayerNorm(hidden_states)\n        return hidden_states\n\n\nclass BertLMPredictionHead(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.transform = BertPredictionHeadTransform(config)\n\n        # The output weights are the same as the input embeddings, but there is\n        # an output-only bias for each token.\n        self.decoder = nn.Linear(config.hidden_size, config.vocab_size, bias=False)\n\n        self.bias = nn.Parameter(torch.zeros(config.vocab_size))\n\n        # Need a link between the two variables so that the bias is correctly resized with `resize_token_embeddings`\n        self.decoder.bias = self.bias\n\n    def forward(self, hidden_states):\n        hidden_states = self.transform(hidden_states)\n        hidden_states = self.decoder(hidden_states)\n        return hidden_states\n\n\nclass BertOnlyMLMHead(nn.Module):\n    def __init__(self, config):\n        super().__init__()\n        self.predictions = BertLMPredictionHead(config)\n\n    def forward(self, sequence_output):\n        prediction_scores = self.predictions(sequence_output)\n        return prediction_scores\n\n\nclass BertPreTrainedModel(PreTrainedModel):\n    \"\"\"\n    An abstract class to handle weights initialization and a simple interface for downloading and loading pretrained\n    models.\n    \"\"\"\n\n    config_class = BertConfig\n    base_model_prefix = \"bert\"\n    _keys_to_ignore_on_load_missing = [r\"position_ids\"]\n\n    def _init_weights(self, module):\n        \"\"\" Initialize the weights \"\"\"\n        if isinstance(module, (nn.Linear, nn.Embedding)):\n            # Slightly different from the TF version which uses truncated_normal for initialization\n            # cf https://github.com/pytorch/pytorch/pull/5617\n            module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)\n        elif isinstance(module, nn.LayerNorm):\n            module.bias.data.zero_()\n            module.weight.data.fill_(1.0)\n        if isinstance(module, nn.Linear) and module.bias is not None:\n            module.bias.data.zero_()\n\n\nclass BertModel(BertPreTrainedModel):\n    \"\"\"\n    The model can behave as an encoder (with only self-attention) as well as a decoder, in which case a layer of\n    cross-attention is added between the self-attention layers, following the architecture described in `Attention is\n    all you need <https://arxiv.org/abs/1706.03762>`__ by Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit,\n    Llion Jones, Aidan N. Gomez, Lukasz Kaiser and Illia Polosukhin.\n    argument and :obj:`add_cross_attention` set to :obj:`True`; an :obj:`encoder_hidden_states` is then expected as an\n    input to the forward pass.\n    \"\"\"\n\n    def __init__(self, config, add_pooling_layer=True):\n        super().__init__(config)\n        self.config = config\n\n        self.embeddings = BertEmbeddings(config)\n        \n        self.encoder = BertEncoder(config)\n\n        self.pooler = BertPooler(config) if add_pooling_layer else None\n\n        self.init_weights()\n \n\n    def get_input_embeddings(self):\n        return self.embeddings.word_embeddings\n\n    def set_input_embeddings(self, value):\n        self.embeddings.word_embeddings = value\n\n    def _prune_heads(self, heads_to_prune):\n        \"\"\"\n        Prunes heads of the model. heads_to_prune: dict of {layer_num: list of heads to prune in this layer} See base\n        class PreTrainedModel\n        \"\"\"\n        for layer, heads in heads_to_prune.items():\n            self.encoder.layer[layer].attention.prune_heads(heads)\n\n    \n    def get_extended_attention_mask(self, attention_mask: Tensor, input_shape: Tuple[int], device: device, is_decoder: bool) -> Tensor:\n        \"\"\"\n        Makes broadcastable attention and causal masks so that future and masked tokens are ignored.\n\n        Arguments:\n            attention_mask (:obj:`torch.Tensor`):\n                Mask with ones indicating tokens to attend to, zeros for tokens to ignore.\n            input_shape (:obj:`Tuple[int]`):\n                The shape of the input to the model.\n            device: (:obj:`torch.device`):\n                The device of the input to the model.\n\n        Returns:\n            :obj:`torch.Tensor` The extended attention mask, with a the same dtype as :obj:`attention_mask.dtype`.\n        \"\"\"\n        # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length]\n        # ourselves in which case we just need to make it broadcastable to all heads.\n        if attention_mask.dim() == 3:\n            extended_attention_mask = attention_mask[:, None, :, :]\n        elif attention_mask.dim() == 2:\n            # Provided a padding mask of dimensions [batch_size, seq_length]\n            # - if the model is a decoder, apply a causal mask in addition to the padding mask\n            # - if the model is an encoder, make the mask broadcastable to [batch_size, num_heads, seq_length, seq_length]\n            if is_decoder:\n                batch_size, seq_length = input_shape\n\n                seq_ids = torch.arange(seq_length, device=device)\n                causal_mask = seq_ids[None, None, :].repeat(batch_size, seq_length, 1) <= seq_ids[None, :, None]\n                # in case past_key_values are used we need to add a prefix ones mask to the causal mask\n                # causal and attention masks must have same type with pytorch version < 1.3\n                causal_mask = causal_mask.to(attention_mask.dtype)\n   \n                if causal_mask.shape[1] < attention_mask.shape[1]:\n                    prefix_seq_len = attention_mask.shape[1] - causal_mask.shape[1]\n                    causal_mask = torch.cat(\n                        [\n                            torch.ones((batch_size, seq_length, prefix_seq_len), device=device, dtype=causal_mask.dtype),\n                            causal_mask,\n                        ],\n                        axis=-1,\n                    )                     \n\n                extended_attention_mask = causal_mask[:, None, :, :] * attention_mask[:, None, None, :]\n            else:\n                extended_attention_mask = attention_mask[:, None, None, :]\n        else:\n            raise ValueError(\n                \"Wrong shape for input_ids (shape {}) or attention_mask (shape {})\".format(\n                    input_shape, attention_mask.shape\n                )\n            )\n\n        # Since attention_mask is 1.0 for positions we want to attend and 0.0 for\n        # masked positions, this operation will create a tensor which is 0.0 for\n        # positions we want to attend and -10000.0 for masked positions.\n        # Since we are adding it to the raw scores before the softmax, this is\n        # effectively the same as removing these entirely.\n        extended_attention_mask = extended_attention_mask.to(dtype=self.dtype)  # fp16 compatibility\n        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0\n        return extended_attention_mask\n    \n    def forward(\n        self,\n        input_ids=None,\n        attention_mask=None,\n        position_ids=None,\n        head_mask=None,\n        inputs_embeds=None,\n        encoder_embeds=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        past_key_values=None,\n        use_cache=None,\n        output_attentions=None,\n        output_hidden_states=None,\n        return_dict=None,\n        is_decoder=False,\n        mode='multimodal',\n    ):\n        r\"\"\"\n        encoder_hidden_states  (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`):\n            Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention if\n            the model is configured as a decoder.\n        encoder_attention_mask (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`):\n            Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used in\n            the cross-attention if the model is configured as a decoder. Mask values selected in ``[0, 1]``:\n            - 1 for tokens that are **not masked**,\n            - 0 for tokens that are **masked**.\n        past_key_values (:obj:`tuple(tuple(torch.FloatTensor))` of length :obj:`config.n_layers` with each tuple having 4 tensors of shape :obj:`(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`):\n            Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up decoding.\n            If :obj:`past_key_values` are used, the user can optionally input only the last :obj:`decoder_input_ids`\n            (those that don't have their past key value states given to this model) of shape :obj:`(batch_size, 1)`\n            instead of all :obj:`decoder_input_ids` of shape :obj:`(batch_size, sequence_length)`.\n        use_cache (:obj:`bool`, `optional`):\n            If set to :obj:`True`, :obj:`past_key_values` key value states are returned and can be used to speed up\n            decoding (see :obj:`past_key_values`).\n        \"\"\"\n        output_attentions = output_attentions if output_attentions is not None else self.config.output_attentions\n        output_hidden_states = (\n            output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states\n        )\n        return_dict = return_dict if return_dict is not None else self.config.use_return_dict\n\n        if is_decoder:\n            use_cache = use_cache if use_cache is not None else self.config.use_cache\n        else:\n            use_cache = False\n\n        if input_ids is not None and inputs_embeds is not None:\n            raise ValueError(\"You cannot specify both input_ids and inputs_embeds at the same time\")\n        elif input_ids is not None:\n            input_shape = input_ids.size()\n            batch_size, seq_length = input_shape\n            device = input_ids.device\n        elif inputs_embeds is not None:\n            input_shape = inputs_embeds.size()[:-1]\n            batch_size, seq_length = input_shape\n            device = inputs_embeds.device\n        elif encoder_embeds is not None:    \n            input_shape = encoder_embeds.size()[:-1]\n            batch_size, seq_length = input_shape \n            device = encoder_embeds.device\n        else:\n            raise ValueError(\"You have to specify either input_ids or inputs_embeds or encoder_embeds\")\n\n        # past_key_values_length\n        past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0\n\n        if attention_mask is None:\n            attention_mask = torch.ones(((batch_size, seq_length + past_key_values_length)), device=device)\n            \n        # We can provide a self-attention mask of dimensions [batch_size, from_seq_length, to_seq_length]\n        # ourselves in which case we just need to make it broadcastable to all heads.\n        extended_attention_mask: torch.Tensor = self.get_extended_attention_mask(attention_mask, input_shape, \n                                                                                 device, is_decoder)\n\n        # If a 2D or 3D attention mask is provided for the cross-attention\n        # we need to make broadcastable to [batch_size, num_heads, seq_length, seq_length]\n        if encoder_hidden_states is not None:\n            if type(encoder_hidden_states) == list:\n                encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states[0].size()\n            else:\n                encoder_batch_size, encoder_sequence_length, _ = encoder_hidden_states.size()\n            encoder_hidden_shape = (encoder_batch_size, encoder_sequence_length)\n            \n            if type(encoder_attention_mask) == list:\n                encoder_extended_attention_mask = [self.invert_attention_mask(mask) for mask in encoder_attention_mask]\n            elif encoder_attention_mask is None:\n                encoder_attention_mask = torch.ones(encoder_hidden_shape, device=device)\n                encoder_extended_attention_mask = self.invert_attention_mask(encoder_attention_mask)\n            else:    \n                encoder_extended_attention_mask = self.invert_attention_mask(encoder_attention_mask)\n        else:\n            encoder_extended_attention_mask = None\n\n        # Prepare head mask if needed\n        # 1.0 in head_mask indicate we keep the head\n        # attention_probs has shape bsz x n_heads x N x N\n        # input head_mask has shape [num_heads] or [num_hidden_layers x num_heads]\n        # and head_mask is converted to shape [num_hidden_layers x batch x num_heads x seq_length x seq_length]\n        head_mask = self.get_head_mask(head_mask, self.config.num_hidden_layers)\n        \n        if encoder_embeds is None:\n            embedding_output = self.embeddings(\n                input_ids=input_ids,\n                position_ids=position_ids,\n                inputs_embeds=inputs_embeds,\n                past_key_values_length=past_key_values_length,\n            )\n        else:\n            embedding_output = encoder_embeds\n            \n        encoder_outputs = self.encoder(\n            embedding_output,\n            attention_mask=extended_attention_mask,\n            head_mask=head_mask,\n            encoder_hidden_states=encoder_hidden_states,\n            encoder_attention_mask=encoder_extended_attention_mask,\n            past_key_values=past_key_values,\n            use_cache=use_cache,\n            output_attentions=output_attentions,\n            output_hidden_states=output_hidden_states,\n            return_dict=return_dict,\n            mode=mode,\n        )\n        sequence_output = encoder_outputs[0]\n        pooled_output = self.pooler(sequence_output) if self.pooler is not None else None\n\n        if not return_dict:\n            return (sequence_output, pooled_output) + encoder_outputs[1:]\n\n        return BaseModelOutputWithPoolingAndCrossAttentions(\n            last_hidden_state=sequence_output,\n            pooler_output=pooled_output,\n            past_key_values=encoder_outputs.past_key_values,\n            hidden_states=encoder_outputs.hidden_states,\n            attentions=encoder_outputs.attentions,\n            cross_attentions=encoder_outputs.cross_attentions,\n        )\n\n\nclass BertLMHeadModel(BertPreTrainedModel):\n\n    _keys_to_ignore_on_load_unexpected = [r\"pooler\"]\n    _keys_to_ignore_on_load_missing = [r\"position_ids\", r\"predictions.decoder.bias\"]\n\n    def __init__(self, config):\n        super().__init__(config)\n\n        self.bert = BertModel(config, add_pooling_layer=False)\n        self.cls = BertOnlyMLMHead(config)\n\n        self.init_weights()\n\n    def get_output_embeddings(self):\n        return self.cls.predictions.decoder\n\n    def set_output_embeddings(self, new_embeddings):\n        self.cls.predictions.decoder = new_embeddings\n\n    def forward(\n        self,\n        input_ids=None,\n        attention_mask=None,\n        position_ids=None,\n        head_mask=None,\n        inputs_embeds=None,\n        encoder_hidden_states=None,\n        encoder_attention_mask=None,\n        labels=None,\n        past_key_values=None,\n        use_cache=None,\n        output_attentions=None,\n        output_hidden_states=None,\n        return_dict=None,\n        return_logits=False,            \n        is_decoder=True,\n        reduction='mean',\n        mode='multimodal', \n    ):\n        r\"\"\"\n        encoder_hidden_states  (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length, hidden_size)`, `optional`):\n            Sequence of hidden-states at the output of the last layer of the encoder. Used in the cross-attention if\n            the model is configured as a decoder.\n        encoder_attention_mask (:obj:`torch.FloatTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`):\n            Mask to avoid performing attention on the padding token indices of the encoder input. This mask is used in\n            the cross-attention if the model is configured as a decoder. Mask values selected in ``[0, 1]``:\n            - 1 for tokens that are **not masked**,\n            - 0 for tokens that are **masked**.\n        labels (:obj:`torch.LongTensor` of shape :obj:`(batch_size, sequence_length)`, `optional`):\n            Labels for computing the left-to-right language modeling loss (next word prediction). Indices should be in\n            ``[-100, 0, ..., config.vocab_size]`` (see ``input_ids`` docstring) Tokens with indices set to ``-100`` are\n            ignored (masked), the loss is only computed for the tokens with labels n ``[0, ..., config.vocab_size]``\n        past_key_values (:obj:`tuple(tuple(torch.FloatTensor))` of length :obj:`config.n_layers` with each tuple having 4 tensors of shape :obj:`(batch_size, num_heads, sequence_length - 1, embed_size_per_head)`):\n            Contains precomputed key and value hidden states of the attention blocks. Can be used to speed up decoding.\n            If :obj:`past_key_values` are used, the user can optionally input only the last :obj:`decoder_input_ids`\n            (those that don't have their past key value states given to this model) of shape :obj:`(batch_size, 1)`\n            instead of all :obj:`decoder_input_ids` of shape :obj:`(batch_size, sequence_length)`.\n        use_cache (:obj:`bool`, `optional`):\n            If set to :obj:`True`, :obj:`past_key_values` key value states are returned and can be used to speed up\n            decoding (see :obj:`past_key_values`).\n        Returns:\n        Example::\n            >>> from transformers import BertTokenizer, BertLMHeadModel, BertConfig\n            >>> import torch\n            >>> tokenizer = BertTokenizer.from_pretrained('bert-base-cased')\n            >>> config = BertConfig.from_pretrained(\"bert-base-cased\")\n            >>> model = BertLMHeadModel.from_pretrained('bert-base-cased', config=config)\n            >>> inputs = tokenizer(\"Hello, my dog is cute\", return_tensors=\"pt\")\n            >>> outputs = model(**inputs)\n            >>> prediction_logits = outputs.logits\n        \"\"\"\n        return_dict = return_dict if return_dict is not None else self.config.use_return_dict\n        if labels is not None:\n            use_cache = False\n\n        outputs = self.bert(\n            input_ids,\n            attention_mask=attention_mask,\n            position_ids=position_ids,\n            head_mask=head_mask,\n            inputs_embeds=inputs_embeds,\n            encoder_hidden_states=encoder_hidden_states,\n            encoder_attention_mask=encoder_attention_mask,\n            past_key_values=past_key_values,\n            use_cache=use_cache,\n            output_attentions=output_attentions,\n            output_hidden_states=output_hidden_states,\n            return_dict=return_dict,\n            is_decoder=is_decoder,\n            mode=mode,\n        )\n        \n        sequence_output = outputs[0]\n        prediction_scores = self.cls(sequence_output)\n        # sequence_output.shape torch.Size([85, 30, 768])\n        # prediction_scores.shape torch.Size([85, 30, 30524])\n        # labels.shape torch.Size([85, 30])\n\n\n        if return_logits:\n            return prediction_scores[:, :-1, :].contiguous()  \n\n        lm_loss = None\n        if labels is not None:\n            # we are doing next-token prediction; shift prediction scores and input ids by one\n            shifted_prediction_scores = prediction_scores[:, :-1, :].contiguous()\n            labels = labels[:, 1:].contiguous()\n            loss_fct = CrossEntropyLoss(reduction=reduction, label_smoothing=0.1) \n            lm_loss = loss_fct(shifted_prediction_scores.view(-1, self.config.vocab_size), labels.view(-1))\n            if reduction=='none':\n                lm_loss = lm_loss.view(prediction_scores.size(0),-1).sum(1)               \n\n        if not return_dict:\n            output = (prediction_scores,) + outputs[2:]\n            return ((lm_loss,) + output) if lm_loss is not None else output\n\n        return CausalLMOutputWithCrossAttentions(\n            loss=lm_loss,\n            logits=prediction_scores,\n            past_key_values=outputs.past_key_values,\n            hidden_states=outputs.hidden_states,\n            attentions=outputs.attentions,\n            cross_attentions=outputs.cross_attentions,\n        )\n\n    def prepare_inputs_for_generation(self, input_ids, past=None, attention_mask=None, **model_kwargs):\n        input_shape = input_ids.shape\n        # if model is used as a decoder in encoder-decoder model, the decoder attention mask is created on the fly\n        if attention_mask is None:\n            attention_mask = input_ids.new_ones(input_shape)\n\n        # cut decoder_input_ids if past is used\n        if past is not None:\n            input_ids = input_ids[:, -1:]\n\n        return {\n            \"input_ids\": input_ids, \n            \"attention_mask\": attention_mask, \n            \"past_key_values\": past,\n            \"encoder_hidden_states\": model_kwargs.get(\"encoder_hidden_states\", None),\n            \"encoder_attention_mask\": model_kwargs.get(\"encoder_attention_mask\", None),\n            \"is_decoder\": True,\n        }\n\n    def _reorder_cache(self, past, beam_idx):\n        reordered_past = ()\n        for layer_past in past:\n            reordered_past += (tuple(past_state.index_select(0, beam_idx) for past_state in layer_past),)\n        return reordered_past\n\n\n"
  },
  {
    "path": "ram/models/ram.py",
    "content": "'''\n * The Recognize Anything Model (RAM)\n * Written by Xinyu Huang\n'''\nimport json\nimport warnings\n\nimport numpy as np\nimport torch\nfrom torch import nn\n\nfrom .bert import BertConfig, BertLMHeadModel, BertModel\nfrom .swin_transformer import SwinTransformer\nfrom .utils import *\n\nwarnings.filterwarnings(\"ignore\")\n\n\n\nclass RAM(nn.Module):\n    def __init__(self,\n                 med_config=f'{CONFIG_PATH}/configs/med_config.json',\n                 image_size=384,\n                 vit='base',\n                 vit_grad_ckpt=False,\n                 vit_ckpt_layer=0,\n                 prompt='a picture of ',\n                 threshold=0.68,\n                 delete_tag_index=[],\n                 tag_list=f'{CONFIG_PATH}/data/ram_tag_list.txt',\n                 tag_list_chinese=f'{CONFIG_PATH}/data/ram_tag_list_chinese.txt'):\n        r\"\"\" The Recognize Anything Model (RAM) inference module.\n        RAM is a strong image tagging model, which can recognize any common category with high accuracy.\n        Described in the paper \" Recognize Anything: A Strong Image Tagging Model\" https://recognize-anything.github.io/\n        \n        Args:\n            med_config (str): path for the mixture of encoder-decoder model's configuration file\n            image_size (int): input image size\n            vit (str): model size of vision transformer\n            threshold (int): tagging threshold\n            delete_tag_index (list): delete some tags that may disturb captioning\n        \"\"\"\n        super().__init__()\n\n        # create image encoder\n        if vit == 'swin_b':\n            if image_size == 224:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_224.json'\n            elif image_size == 384:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_384.json'\n            vision_config = read_json(vision_config_path)\n            assert image_size == vision_config['image_res']\n            # assert config['patch_size'] == 32\n            vision_width = vision_config['vision_width']\n\n            self.visual_encoder = SwinTransformer(\n                img_size=vision_config['image_res'],\n                patch_size=4,\n                in_chans=3,\n                embed_dim=vision_config['embed_dim'],\n                depths=vision_config['depths'],\n                num_heads=vision_config['num_heads'],\n                window_size=vision_config['window_size'],\n                mlp_ratio=4.,\n                qkv_bias=True,\n                drop_rate=0.0,\n                drop_path_rate=0.1,\n                ape=False,\n                patch_norm=True,\n                use_checkpoint=False)\n\n        elif vit == 'swin_l':\n            if image_size == 224:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_224.json'\n            elif image_size == 384:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_384.json'\n            elif image_size == 444:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_444.json'\n            vision_config = read_json(vision_config_path)\n            assert image_size == vision_config['image_res']\n            # assert config['patch_size'] == 32\n            vision_width = vision_config['vision_width']\n\n            self.visual_encoder = SwinTransformer(\n                img_size=vision_config['image_res'],\n                patch_size=4,\n                in_chans=3,\n                embed_dim=vision_config['embed_dim'],\n                depths=vision_config['depths'],\n                num_heads=vision_config['num_heads'],\n                window_size=vision_config['window_size'],\n                mlp_ratio=4.,\n                qkv_bias=True,\n                drop_rate=0.0,\n                drop_path_rate=0.1,\n                ape=False,\n                patch_norm=True,\n                use_checkpoint=False)\n\n        else:\n            self.visual_encoder, vision_width = create_vit(\n                vit, image_size, vit_grad_ckpt, vit_ckpt_layer)\n\n        # create tokenzier\n        self.tokenizer = init_tokenizer()\n\n        # Tag2Text employ encoder-decoder architecture for image-tag-text generation: image-tag interaction encoder and image-tag-text decoder\n        # create image-tag interaction encoder\n        encoder_config = BertConfig.from_json_file(med_config)\n        encoder_config.encoder_width = 512\n        self.tag_encoder = BertModel(config=encoder_config,\n                                     add_pooling_layer=False)\n\n        # create image-tag-text decoder\n        decoder_config = BertConfig.from_json_file(med_config)\n        self.text_decoder = BertLMHeadModel(config=decoder_config)\n\n        self.delete_tag_index = delete_tag_index\n        self.prompt = prompt\n        self.prompt_length = len(self.tokenizer(self.prompt).input_ids) - 1\n\n        # load tag list\n        self.tag_list = self.load_tag_list(tag_list)\n        self.tag_list_chinese = self.load_tag_list(tag_list_chinese)\n\n        # create image-tag recognition decoder\n        self.threshold = threshold\n        self.num_class = len(self.tag_list)\n        q2l_config = BertConfig.from_json_file(f'{CONFIG_PATH}/configs/q2l_config.json')\n        q2l_config.encoder_width = 512\n        self.tagging_head = BertModel(config=q2l_config,\n                                      add_pooling_layer=False)\n        self.tagging_head.resize_token_embeddings(len(self.tokenizer))\n        # self.label_embed = nn.Embedding(self.num_class, q2l_config.hidden_size)\n        self.label_embed = nn.Parameter(torch.zeros(self.num_class, q2l_config.encoder_width))\n\n        if q2l_config.hidden_size != 512:\n            self.wordvec_proj = nn.Linear(512, q2l_config.hidden_size)\n        else:\n            self.wordvec_proj = nn.Identity()\n\n        self.fc = nn.Linear(q2l_config.hidden_size, 1)\n\n        self.del_selfattention()\n\n        # share weights of the lowest 2-layer of \"image-tag interaction encoder\" with the \"image-tag recogntion decoder\"\n        tie_encoder_decoder_weights(self.tag_encoder, self.tagging_head, '',\n                                    ' ')\n        self.image_proj = nn.Linear(vision_width, 512)\n        # self.label_embed = nn.Parameter(torch.load(f'{CONFIG_PATH}/data/textual_label_embedding.pth',map_location='cpu').float())\n\n        # adjust thresholds for some tags\n        self.class_threshold = torch.ones(self.num_class) * self.threshold\n        ram_class_threshold_path = f'{CONFIG_PATH}/data/ram_tag_list_threshold.txt'\n        with open(ram_class_threshold_path, 'r', encoding='utf-8') as f:\n            ram_class_threshold = [float(s.strip()) for s in f]\n        for key,value in enumerate(ram_class_threshold):\n            self.class_threshold[key] = value\n\n    def load_tag_list(self, tag_list_file):\n        with open(tag_list_file, 'r', encoding=\"utf-8\") as f:\n            tag_list = f.read().splitlines()\n        tag_list = np.array(tag_list)\n        return tag_list\n\n    # delete self-attention layer of image-tag recognition decoder to reduce computation, follower Query2Label\n    def del_selfattention(self):\n        del self.tagging_head.embeddings\n        for layer in self.tagging_head.encoder.layer:\n            del layer.attention\n\n    def condition_forward(self,\n                 image,\n                 threshold=0.68,\n                 condition_flag=None,\n                 tag_input=None,\n                 only_feature=True,\n                 ):\n            \n        label_embed = torch.nn.functional.relu(self.wordvec_proj(self.label_embed))\n\n        image_embeds = self.image_proj(self.visual_encoder(image))\n        if only_feature:\n            return image_embeds\n        else:\n            image_atts = torch.ones(image_embeds.size()[:-1],\n                                    dtype=torch.long).to(image.device)\n\n            # recognized image tags using image-tag recogntiion decoder\n            image_cls_embeds = image_embeds[:, 0, :]\n            image_spatial_embeds = image_embeds[:, 1:, :]\n\n            bs = image_spatial_embeds.shape[0]\n            label_embed = label_embed.unsqueeze(0).repeat(bs, 1, 1)\n            tagging_embed = self.tagging_head(\n                encoder_embeds=label_embed,\n                encoder_hidden_states=image_embeds,\n                encoder_attention_mask=image_atts,\n                return_dict=False,\n                mode='tagging',\n            )\n\n            logits = self.fc(tagging_embed[0]).squeeze(-1)\n\n            targets = torch.where(\n                torch.sigmoid(logits) > self.class_threshold.to(image.device),\n                torch.tensor(1.0).to(image.device),\n                torch.zeros(self.num_class).to(image.device))\n\n            return image_embeds, logits, targets\n\n    def generate_tag(self,\n                 image,\n                 threshold=0.68,\n                 tag_input=None,\n                 ):\n            \n        label_embed = torch.nn.functional.relu(self.wordvec_proj(self.label_embed))\n\n        image_embeds = self.image_proj(self.visual_encoder(image))\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # recognized image tags using image-tag recogntiion decoder\n        image_cls_embeds = image_embeds[:, 0, :]\n        image_spatial_embeds = image_embeds[:, 1:, :]\n\n        bs = image_spatial_embeds.shape[0]\n        label_embed = label_embed.unsqueeze(0).repeat(bs, 1, 1)\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0]).squeeze(-1)\n\n        targets = torch.where(\n            torch.sigmoid(logits) > self.class_threshold.to(image.device),\n            torch.tensor(1.0).to(image.device),\n            torch.zeros(self.num_class).to(image.device))\n\n        tag = targets.cpu().numpy()\n        tag[:,self.delete_tag_index] = 0\n        tag_output = []\n        tag_output_chinese = []\n        for b in range(bs):\n            index = np.argwhere(tag[b] == 1)\n            token = self.tag_list[index].squeeze(axis=1)\n            # tag_output.append(' | '.join(token))\n            tag_output.append(', '.join(token))\n            token_chinese = self.tag_list_chinese[index].squeeze(axis=1)\n            # tag_output_chinese.append(' | '.join(token_chinese))\n            tag_output_chinese.append(', '.join(token_chinese))\n\n\n        return tag_output, tag_output_chinese\n\n    def generate_tag_openset(self,\n                 image,\n                 threshold=0.68,\n                 tag_input=None,\n                 ):\n            \n        label_embed = torch.nn.functional.relu(self.wordvec_proj(self.label_embed))\n\n        image_embeds = self.image_proj(self.visual_encoder(image))\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # recognized image tags using image-tag recogntiion decoder\n        image_cls_embeds = image_embeds[:, 0, :]\n        image_spatial_embeds = image_embeds[:, 1:, :]\n\n        bs = image_spatial_embeds.shape[0]\n        label_embed = label_embed.unsqueeze(0).repeat(bs, 1, 1)\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0]).squeeze(-1)\n\n        targets = torch.where(\n            torch.sigmoid(logits) > self.class_threshold.to(image.device),\n            torch.tensor(1.0).to(image.device),\n            torch.zeros(self.num_class).to(image.device))\n\n        tag = targets.cpu().numpy()\n        tag[:,self.delete_tag_index] = 0\n        tag_output = []\n        for b in range(bs):\n            index = np.argwhere(tag[b] == 1)\n            token = self.tag_list[index].squeeze(axis=1)\n            tag_output.append(' | '.join(token))\n\n        return tag_output\n\n\n# load RAM pretrained model parameters\ndef ram(pretrained='', **kwargs):\n    model = RAM(**kwargs)\n    if pretrained:\n        if kwargs['vit'] == 'swin_b':\n            model, msg = load_checkpoint_swinbase(model, pretrained, kwargs)\n        elif kwargs['vit'] == 'swin_l':\n            model, msg = load_checkpoint_swinlarge(model, pretrained, kwargs)\n        else:\n            model, msg = load_checkpoint(model, pretrained)\n        print('vit:', kwargs['vit'])\n#         print('msg', msg)\n    return model\n"
  },
  {
    "path": "ram/models/ram_lora.py",
    "content": "'''\n * The Recognize Anything Model (RAM)\n * Written by Xinyu Huang\n'''\nimport json\nimport warnings\n\nimport numpy as np\nimport torch\nfrom torch import nn\n\n\nfrom .bert_lora import BertConfig, BertLMHeadModel, BertModel\nfrom .swin_transformer_lora import SwinTransformer\nfrom .utils import *\n\nwarnings.filterwarnings(\"ignore\")\n\n\n\nclass RAMLora(nn.Module):\n    def __init__(self,\n                 condition_config=f'{CONFIG_PATH}/configs/condition_config.json',\n                 med_config=f'{CONFIG_PATH}/configs/med_config.json',\n                 image_size=384,\n                 vit='base',\n                 vit_grad_ckpt=False,\n                 vit_ckpt_layer=0,\n                 prompt='a picture of ',\n                 threshold=0.68,\n                 max_threthold=0.9,\n                 add_threthold=0,\n                 delete_tag_index=[],\n                 tag_list=f'{CONFIG_PATH}/data/ram_tag_list.txt',\n                 tag_list_chinese=f'{CONFIG_PATH}/data/ram_tag_list_chinese.txt'):\n        r\"\"\" The Recognize Anything Model (RAM) inference module.\n        RAM is a strong image tagging model, which can recognize any common category with high accuracy.\n        Described in the paper \" Recognize Anything: A Strong Image Tagging Model\" https://recognize-anything.github.io/\n        \n        Args:\n            med_config (str): path for the mixture of encoder-decoder model's configuration file\n            image_size (int): input image size\n            vit (str): model size of vision transformer\n            threshold (int): tagging threshold\n            delete_tag_index (list): delete some tags that may disturb captioning\n        \"\"\"\n        super().__init__()\n\n        # create image encoder\n        if vit == 'swin_b':\n            if image_size == 224:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_224.json'\n            elif image_size == 384:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_384.json'\n            vision_config = read_json(vision_config_path)\n            assert image_size == vision_config['image_res']\n            # assert config['patch_size'] == 32\n            vision_width = vision_config['vision_width']\n\n            self.visual_encoder = SwinTransformer(\n                img_size=vision_config['image_res'],\n                patch_size=4,\n                in_chans=3,\n                embed_dim=vision_config['embed_dim'],\n                depths=vision_config['depths'],\n                num_heads=vision_config['num_heads'],\n                window_size=vision_config['window_size'],\n                mlp_ratio=4.,\n                qkv_bias=True,\n                drop_rate=0.0,\n                drop_path_rate=0.1,\n                ape=False,\n                patch_norm=True,\n                use_checkpoint=False)\n\n        elif vit == 'swin_l':\n            if image_size == 224:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_224.json'\n            elif image_size == 384:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_384.json'\n            elif image_size == 444:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_444.json'\n            vision_config = read_json(vision_config_path)\n            assert image_size == vision_config['image_res']\n            # assert config['patch_size'] == 32\n            vision_width = vision_config['vision_width']\n\n            self.visual_encoder = SwinTransformer(\n                img_size=vision_config['image_res'],\n                patch_size=4,\n                in_chans=3,\n                embed_dim=vision_config['embed_dim'],\n                depths=vision_config['depths'],\n                num_heads=vision_config['num_heads'],\n                window_size=vision_config['window_size'],\n                mlp_ratio=4.,\n                qkv_bias=True,\n                drop_rate=0.0,\n                drop_path_rate=0.1,\n                ape=False,\n                patch_norm=True,\n                use_checkpoint=False)\n\n        else:\n            self.visual_encoder, vision_width = create_vit(\n                vit, image_size, vit_grad_ckpt, vit_ckpt_layer)\n\n        # create tokenzier\n        self.tokenizer = init_tokenizer()\n\n        # Tag2Text employ encoder-decoder architecture for image-tag-text generation: image-tag interaction encoder and image-tag-text decoder\n        # create image-tag interaction encoder\n        encoder_config = BertConfig.from_json_file(med_config)\n        encoder_config.encoder_width = 512\n        self.tag_encoder = BertModel(config=encoder_config,\n                                     add_pooling_layer=False)\n\n        # create image-tag-text decoder\n        decoder_config = BertConfig.from_json_file(med_config)\n        self.text_decoder = BertLMHeadModel(config=decoder_config)\n\n        self.delete_tag_index = delete_tag_index\n        self.prompt = prompt\n        self.prompt_length = len(self.tokenizer(self.prompt).input_ids) - 1\n\n        # load tag list\n        self.tag_list = self.load_tag_list(tag_list)\n        self.tag_list_chinese = self.load_tag_list(tag_list_chinese)\n\n        # create image-tag recognition decoder\n        self.threshold = threshold\n        self.num_class = len(self.tag_list)\n        q2l_config = BertConfig.from_json_file(f'{CONFIG_PATH}/configs/q2l_config.json')\n        q2l_config.encoder_width = 512\n        self.tagging_head = BertModel(config=q2l_config,\n                                      add_pooling_layer=False)\n        self.tagging_head.resize_token_embeddings(len(self.tokenizer))\n        # self.label_embed = nn.Embedding(self.num_class, q2l_config.hidden_size)\n        self.label_embed = nn.Parameter(torch.zeros(self.num_class, q2l_config.encoder_width))\n\n        if q2l_config.hidden_size != 512:\n            self.wordvec_proj = nn.Linear(512, q2l_config.hidden_size)\n        else:\n            self.wordvec_proj = nn.Identity()\n\n        self.fc = nn.Linear(q2l_config.hidden_size, 1)\n\n        self.del_selfattention()\n\n        # share weights of the lowest 2-layer of \"image-tag interaction encoder\" with the \"image-tag recogntion decoder\"\n        tie_encoder_decoder_weights(self.tag_encoder, self.tagging_head, '',\n                                    ' ')\n        self.image_proj = nn.Linear(vision_width, 512)\n        # self.label_embed = nn.Parameter(torch.load(f'{CONFIG_PATH}/data/textual_label_embedding.pth',map_location='cpu').float())\n\n        # adjust thresholds for some tags\n        self.class_threshold = torch.ones(self.num_class) * self.threshold\n\n        print(f'Loading default thretholds from .txt....')\n        ram_class_threshold_path = f'{CONFIG_PATH}/data/ram_tag_list_threshold.txt'\n        with open(ram_class_threshold_path, 'r', encoding='utf-8') as f:\n            ram_class_threshold = [float(s.strip()) for s in f]\n        for key,value in enumerate(ram_class_threshold):\n            if value > max_threthold:\n                self.class_threshold[key] = value\n            else:\n                self.class_threshold[key] = min(value + add_threthold, max_threthold)\n\n        \n\n    def load_tag_list(self, tag_list_file):\n        with open(tag_list_file, 'r', encoding=\"utf-8\") as f:\n            tag_list = f.read().splitlines()\n        tag_list = np.array(tag_list)\n        return tag_list\n\n    # delete self-attention layer of image-tag recognition decoder to reduce computation, follower Query2Label\n    def del_selfattention(self):\n        del self.tagging_head.embeddings\n        for layer in self.tagging_head.encoder.layer:\n            del layer.attention\n\n    def generate_image_embeds(self,\n                 image,\n                 condition=False\n                 ):\n            \n        image_embeds = self.image_proj(self.visual_encoder(image))\n        \n        return image_embeds\n\n    def generate_tag(self,\n                 image,\n                 threshold=0.68,\n                 tag_input=None,\n                 ):\n            \n        label_embed = torch.nn.functional.relu(self.wordvec_proj(self.label_embed))\n\n        image_embeds = self.image_proj(self.visual_encoder(image))\n\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # recognized image tags using image-tag recogntiion decoder\n        image_cls_embeds = image_embeds[:, 0, :]\n        image_spatial_embeds = image_embeds[:, 1:, :]\n\n        bs = image_spatial_embeds.shape[0]\n        label_embed = label_embed.unsqueeze(0).repeat(bs, 1, 1)\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0]).squeeze(-1)\n        targets = torch.where(\n            torch.sigmoid(logits) > self.class_threshold.to(image.device),\n            torch.tensor(1.0).to(image.device),\n            torch.zeros(self.num_class).to(image.device))\n\n        tag = targets.cpu().numpy()\n        tag[:,self.delete_tag_index] = 0\n        tag_output = []\n        tag_output_chinese = []\n        for b in range(bs):\n            index = np.argwhere(tag[b] == 1)\n            token = self.tag_list[index].squeeze(axis=1)\n            # tag_output.append(' | '.join(token))\n            tag_output.append(', '.join(token))\n            token_chinese = self.tag_list_chinese[index].squeeze(axis=1)\n            # tag_output_chinese.append(' | '.join(token_chinese))\n            tag_output_chinese.append(', '.join(token_chinese))\n\n\n        return tag_output, tag_output_chinese\n\n    \n\n    def condition_forward(self,\n                 image,\n                 threshold=0.68,\n                 condition_flag=None,\n                 tag_input=None,\n                 only_feature=True\n                 ):\n            \n        label_embed = torch.nn.functional.relu(self.wordvec_proj(self.label_embed))\n        image_embeds = self.image_proj(self.visual_encoder(image))\n\n        if only_feature:\n            return image_embeds\n        else:\n            image_atts = torch.ones(image_embeds.size()[:-1],\n                                    dtype=torch.long).to(image.device)\n\n            # recognized image tags using image-tag recogntiion decoder\n            image_cls_embeds = image_embeds[:, 0, :]\n            image_spatial_embeds = image_embeds[:, 1:, :]\n\n            bs = image_spatial_embeds.shape[0]\n            label_embed = label_embed.unsqueeze(0).repeat(bs, 1, 1)\n            tagging_embed = self.tagging_head(\n                encoder_embeds=label_embed,\n                encoder_hidden_states=image_embeds,\n                encoder_attention_mask=image_atts,\n                return_dict=False,\n                mode='tagging',\n            )\n\n            logits = self.fc(tagging_embed[0]).squeeze(-1)\n\n            targets = torch.where(\n                torch.sigmoid(logits) > self.class_threshold.to(image.device),\n                torch.tensor(1.0).to(image.device),\n                torch.zeros(self.num_class).to(image.device))\n\n            return image_embeds, logits, targets\n\n    def generate_tag_openset(self,\n                 image,\n                 threshold=0.68,\n                 tag_input=None,\n                 ):\n            \n        label_embed = torch.nn.functional.relu(self.wordvec_proj(self.label_embed))\n\n        image_embeds = self.image_proj(self.visual_encoder(image))\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # recognized image tags using image-tag recogntiion decoder\n        image_cls_embeds = image_embeds[:, 0, :]\n        image_spatial_embeds = image_embeds[:, 1:, :]\n\n        bs = image_spatial_embeds.shape[0]\n        label_embed = label_embed.unsqueeze(0).repeat(bs, 1, 1)\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0]).squeeze(-1)\n\n        targets = torch.where(\n            torch.sigmoid(logits) > self.class_threshold.to(image.device),\n            torch.tensor(1.0).to(image.device),\n            torch.zeros(self.num_class).to(image.device))\n\n        tag = targets.cpu().numpy()\n        tag[:,self.delete_tag_index] = 0\n        tag_output = []\n        for b in range(bs):\n            index = np.argwhere(tag[b] == 1)\n            token = self.tag_list[index].squeeze(axis=1)\n            tag_output.append(' | '.join(token))\n\n        return tag_output\n\n\n# load RAM pretrained model parameters\ndef ram(pretrained='', pretrained_condition='', **kwargs):\n    model = RAMLora(**kwargs)\n\n    if pretrained:\n        if kwargs['vit'] == 'swin_b':\n            model, msg = load_checkpoint_swinbase(model, pretrained, kwargs)\n        elif kwargs['vit'] == 'swin_l':\n            model, msg = load_checkpoint_swinlarge(model, pretrained, kwargs)\n        else:\n            model, msg = load_checkpoint(model, pretrained)\n        print('vit:', kwargs['vit'])\n    \n    if pretrained_condition:\n        model.load_state_dict(torch.load(pretrained_condition), strict=False)\n        print(f'load lora from {pretrained_condition}')\n\n    return model\n"
  },
  {
    "path": "ram/models/swin_transformer.py",
    "content": "# --------------------------------------------------------\n# Swin Transformer\n# Copyright (c) 2021 Microsoft\n# Licensed under The MIT License [see LICENSE for details]\n# Written by Ze Liu\n# --------------------------------------------------------\n\nimport numpy as np\nfrom scipy import interpolate\n\nimport torch\nimport torch.nn as nn\nimport torch.utils.checkpoint as checkpoint\nfrom timm.models.layers import DropPath, to_2tuple, trunc_normal_\n\n\nclass Mlp(nn.Module):\n    def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):\n        super().__init__()\n        out_features = out_features or in_features\n        hidden_features = hidden_features or in_features\n        self.fc1 = nn.Linear(in_features, hidden_features)\n        self.act = act_layer()\n        self.fc2 = nn.Linear(hidden_features, out_features)\n        self.drop = nn.Dropout(drop)\n\n    def forward(self, x):\n        x = self.fc1(x)\n        x = self.act(x)\n        x = self.drop(x)\n        x = self.fc2(x)\n        x = self.drop(x)\n        return x\n\n\ndef window_partition(x, window_size):\n    \"\"\"\n    Args:\n        x: (B, H, W, C)\n        window_size (int): window size\n\n    Returns:\n        windows: (num_windows*B, window_size, window_size, C)\n    \"\"\"\n    B, H, W, C = x.shape\n    x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)\n    windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)\n    return windows\n\n\ndef window_reverse(windows, window_size, H, W):\n    \"\"\"\n    Args:\n        windows: (num_windows*B, window_size, window_size, C)\n        window_size (int): Window size\n        H (int): Height of image\n        W (int): Width of image\n\n    Returns:\n        x: (B, H, W, C)\n    \"\"\"\n    B = int(windows.shape[0] / (H * W / window_size / window_size))\n    x = windows.view(B, H // window_size, W // window_size, window_size, window_size, -1)\n    x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)\n    return x\n\n\nclass WindowAttention(nn.Module):\n    r\"\"\" Window based multi-head self attention (W-MSA) module with relative position bias.\n    It supports both of shifted and non-shifted window.\n\n    Args:\n        dim (int): Number of input channels.\n        window_size (tuple[int]): The height and width of the window.\n        num_heads (int): Number of attention heads.\n        qkv_bias (bool, optional):  If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set\n        attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0\n        proj_drop (float, optional): Dropout ratio of output. Default: 0.0\n    \"\"\"\n\n    def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):\n\n        super().__init__()\n        self.dim = dim\n        self.window_size = window_size  # Wh, Ww\n        self.num_heads = num_heads\n        head_dim = dim // num_heads\n        self.scale = qk_scale or head_dim ** -0.5\n\n        # define a parameter table of relative position bias\n        self.relative_position_bias_table = nn.Parameter(\n            torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads))  # 2*Wh-1 * 2*Ww-1, nH\n\n        # get pair-wise relative position index for each token inside the window\n        coords_h = torch.arange(self.window_size[0])\n        coords_w = torch.arange(self.window_size[1])\n        coords = torch.stack(torch.meshgrid([coords_h, coords_w]))  # 2, Wh, Ww\n        coords_flatten = torch.flatten(coords, 1)  # 2, Wh*Ww\n        relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]  # 2, Wh*Ww, Wh*Ww\n        relative_coords = relative_coords.permute(1, 2, 0).contiguous()  # Wh*Ww, Wh*Ww, 2\n        relative_coords[:, :, 0] += self.window_size[0] - 1  # shift to start from 0\n        relative_coords[:, :, 1] += self.window_size[1] - 1\n        relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1\n        relative_position_index = relative_coords.sum(-1)  # Wh*Ww, Wh*Ww\n        self.register_buffer(\"relative_position_index\", relative_position_index)\n\n        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)\n        self.attn_drop = nn.Dropout(attn_drop)\n        self.proj = nn.Linear(dim, dim)\n        self.proj_drop = nn.Dropout(proj_drop)\n\n        trunc_normal_(self.relative_position_bias_table, std=.02)\n        self.softmax = nn.Softmax(dim=-1)\n\n    def forward(self, x, mask=None):\n        \"\"\"\n        Args:\n            x: input features with shape of (num_windows*B, N, C)\n            mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None\n        \"\"\"\n        B_, N, C = x.shape\n        qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)\n        q, k, v = qkv[0], qkv[1], qkv[2]  # make torchscript happy (cannot use tensor as tuple)\n\n        q = q * self.scale\n        attn = (q @ k.transpose(-2, -1))\n\n        relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(\n            self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1)  # Wh*Ww,Wh*Ww,nH\n        relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()  # nH, Wh*Ww, Wh*Ww\n        attn = attn + relative_position_bias.unsqueeze(0)\n\n        if mask is not None:\n            nW = mask.shape[0]\n            attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)\n            attn = attn.view(-1, self.num_heads, N, N)\n            attn = self.softmax(attn)\n        else:\n            attn = self.softmax(attn)\n\n        attn = self.attn_drop(attn)\n\n        x = (attn @ v).transpose(1, 2).reshape(B_, N, C)\n        x = self.proj(x)\n        x = self.proj_drop(x)\n        return x\n\n    def extra_repr(self) -> str:\n        return f'dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}'\n\n    def flops(self, N):\n        # calculate flops for 1 window with token length of N\n        flops = 0\n        # qkv = self.qkv(x)\n        flops += N * self.dim * 3 * self.dim\n        # attn = (q @ k.transpose(-2, -1))\n        flops += self.num_heads * N * (self.dim // self.num_heads) * N\n        #  x = (attn @ v)\n        flops += self.num_heads * N * N * (self.dim // self.num_heads)\n        # x = self.proj(x)\n        flops += N * self.dim * self.dim\n        return flops\n\n\nclass SwinTransformerBlock(nn.Module):\n    r\"\"\" Swin Transformer Block.\n\n    Args:\n        dim (int): Number of input channels.\n        input_resolution (tuple[int]): Input resulotion.\n        num_heads (int): Number of attention heads.\n        window_size (int): Window size.\n        shift_size (int): Shift size for SW-MSA.\n        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.\n        qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.\n        drop (float, optional): Dropout rate. Default: 0.0\n        attn_drop (float, optional): Attention dropout rate. Default: 0.0\n        drop_path (float, optional): Stochastic depth rate. Default: 0.0\n        act_layer (nn.Module, optional): Activation layer. Default: nn.GELU\n        norm_layer (nn.Module, optional): Normalization layer.  Default: nn.LayerNorm\n    \"\"\"\n\n    def __init__(self, dim, input_resolution, num_heads, window_size=7, shift_size=0,\n                 mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0., drop_path=0.,\n                 act_layer=nn.GELU, norm_layer=nn.LayerNorm):\n        super().__init__()\n        self.dim = dim\n        self.input_resolution = input_resolution\n        self.num_heads = num_heads\n        self.window_size = window_size\n        self.shift_size = shift_size\n        self.mlp_ratio = mlp_ratio\n        if min(self.input_resolution) <= self.window_size:\n            # if window size is larger than input resolution, we don't partition windows\n            self.shift_size = 0\n            self.window_size = min(self.input_resolution)\n        assert 0 <= self.shift_size < self.window_size, \"shift_size must in 0-window_size\"\n\n        self.norm1 = norm_layer(dim)\n        self.attn = WindowAttention(\n            dim, window_size=to_2tuple(self.window_size), num_heads=num_heads,\n            qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)\n\n        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()\n        self.norm2 = norm_layer(dim)\n        mlp_hidden_dim = int(dim * mlp_ratio)\n        self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)\n\n        if self.shift_size > 0:\n            # calculate attention mask for SW-MSA\n            H, W = self.input_resolution\n            img_mask = torch.zeros((1, H, W, 1))  # 1 H W 1\n            h_slices = (slice(0, -self.window_size),\n                        slice(-self.window_size, -self.shift_size),\n                        slice(-self.shift_size, None))\n            w_slices = (slice(0, -self.window_size),\n                        slice(-self.window_size, -self.shift_size),\n                        slice(-self.shift_size, None))\n            cnt = 0\n            for h in h_slices:\n                for w in w_slices:\n                    img_mask[:, h, w, :] = cnt\n                    cnt += 1\n\n            mask_windows = window_partition(img_mask, self.window_size)  # nW, window_size, window_size, 1\n            mask_windows = mask_windows.view(-1, self.window_size * self.window_size)\n            attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)\n            attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))\n        else:\n            attn_mask = None\n\n        self.register_buffer(\"attn_mask\", attn_mask)\n\n        ## condition from LR\n        self.condition_attention = nn.Sequential(\n            nn.Linear(256, dim*2, bias=False),\n        )\n        self.condition_ffn = nn.Sequential(\n            nn.Linear(256, dim*2, bias=False),\n        )\n\n        zero_module(self.condition_attention)\n        zero_module(self.condition_ffn)\n\n    def forward(self, x, condition=None):\n        H, W = self.input_resolution\n        B, L, C = x.shape\n        assert L == H * W, \"input feature has wrong size\"\n\n        shortcut = x\n        x = self.norm1(x)\n        x = x.view(B, H, W, C)\n\n        # add condition before attention\n        # input B,H,W,C\n        if condition is not None:\n            x = x.permute(0, 3, 1, 2) # BCHW\n            condition_attention = self.condition_attention(condition).view(-1, 2*C, 1, 1)\n            condition_attn_multiplication, condition_attn_addition = condition_attention.chunk(2, dim=1)\n            x = x*condition_attn_multiplication + condition_attn_multiplication\n            x = x.permute(0, 2, 3, 1)\n\n\n\n        # cyclic shift\n        if self.shift_size > 0:\n            shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))\n        else:\n            shifted_x = x\n\n        # partition windows\n        x_windows = window_partition(shifted_x, self.window_size)  # nW*B, window_size, window_size, C\n        x_windows = x_windows.view(-1, self.window_size * self.window_size, C)  # nW*B, window_size*window_size, C\n\n        # W-MSA/SW-MSA\n        attn_windows = self.attn(x_windows, mask=self.attn_mask)  # nW*B, window_size*window_size, C\n\n        # merge windows\n        attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)\n        shifted_x = window_reverse(attn_windows, self.window_size, H, W)  # B H' W' C\n\n        # reverse cyclic shift\n        if self.shift_size > 0:\n            x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))\n        else:\n            x = shifted_x\n        x = x.view(B, H * W, C)\n\n        # FFN\n        x = shortcut + self.drop_path(x)\n        # x = x + self.drop_path(self.mlp(self.norm2(x)))\n        \n        # add condition before ffn\n        # input B,H*W,C\n        if condition is not None:\n            res = x\n            x = self.norm2(x)\n            x = x.view(B, H, W, C)\n            x = x.permute(0, 3, 1, 2) # BCHW\n            condition_ffn = self.condition_ffn(condition).view(-1, 2*C, 1, 1)\n            condition_ffn_multiplication, condition_ffn_addition = condition_ffn.chunk(2, dim=1)\n            x = x*condition_ffn_multiplication + condition_ffn_addition\n            x = x.permute(0, 2, 3, 1)\n            x = x.view(B, H*W, C)\n            x = res + self.drop_path(self.mlp(x))\n        else:\n            x = x + self.drop_path(self.mlp(self.norm2(x)))\n        return x\n\n    def extra_repr(self) -> str:\n        return f\"dim={self.dim}, input_resolution={self.input_resolution}, num_heads={self.num_heads}, \" \\\n               f\"window_size={self.window_size}, shift_size={self.shift_size}, mlp_ratio={self.mlp_ratio}\"\n\n    def flops(self):\n        flops = 0\n        H, W = self.input_resolution\n        # norm1\n        flops += self.dim * H * W\n        # W-MSA/SW-MSA\n        nW = H * W / self.window_size / self.window_size\n        flops += nW * self.attn.flops(self.window_size * self.window_size)\n        # mlp\n        flops += 2 * H * W * self.dim * self.dim * self.mlp_ratio\n        # norm2\n        flops += self.dim * H * W\n        return flops\n\n\nclass PatchMerging(nn.Module):\n    r\"\"\" Patch Merging Layer.\n\n    Args:\n        input_resolution (tuple[int]): Resolution of input feature.\n        dim (int): Number of input channels.\n        norm_layer (nn.Module, optional): Normalization layer.  Default: nn.LayerNorm\n    \"\"\"\n\n    def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):\n        super().__init__()\n        self.input_resolution = input_resolution\n        self.dim = dim\n        self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)\n        self.norm = norm_layer(4 * dim)\n\n    def forward(self, x):\n        \"\"\"\n        x: B, H*W, C\n        \"\"\"\n        H, W = self.input_resolution\n        B, L, C = x.shape\n        assert L == H * W, \"input feature has wrong size\"\n        assert H % 2 == 0 and W % 2 == 0, f\"x size ({H}*{W}) are not even.\"\n\n        x = x.view(B, H, W, C)\n\n        x0 = x[:, 0::2, 0::2, :]  # B H/2 W/2 C\n        x1 = x[:, 1::2, 0::2, :]  # B H/2 W/2 C\n        x2 = x[:, 0::2, 1::2, :]  # B H/2 W/2 C\n        x3 = x[:, 1::2, 1::2, :]  # B H/2 W/2 C\n        x = torch.cat([x0, x1, x2, x3], -1)  # B H/2 W/2 4*C\n        x = x.view(B, -1, 4 * C)  # B H/2*W/2 4*C\n\n        x = self.norm(x)\n        x = self.reduction(x)\n\n        return x\n\n    def extra_repr(self) -> str:\n        return f\"input_resolution={self.input_resolution}, dim={self.dim}\"\n\n    def flops(self):\n        H, W = self.input_resolution\n        flops = H * W * self.dim\n        flops += (H // 2) * (W // 2) * 4 * self.dim * 2 * self.dim\n        return flops\n\n\nclass BasicLayer(nn.Module):\n    \"\"\" A basic Swin Transformer layer for one stage.\n\n    Args:\n        dim (int): Number of input channels.\n        input_resolution (tuple[int]): Input resolution.\n        depth (int): Number of blocks.\n        num_heads (int): Number of attention heads.\n        window_size (int): Local window size.\n        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.\n        qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.\n        drop (float, optional): Dropout rate. Default: 0.0\n        attn_drop (float, optional): Attention dropout rate. Default: 0.0\n        drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0\n        norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm\n        downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None\n        use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.\n    \"\"\"\n\n    def __init__(self, dim, input_resolution, depth, num_heads, window_size,\n                 mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0.,\n                 drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False):\n\n        super().__init__()\n        self.dim = dim\n        self.input_resolution = input_resolution\n        self.depth = depth\n        self.use_checkpoint = use_checkpoint\n\n        # build blocks\n        self.blocks = nn.ModuleList([\n            SwinTransformerBlock(dim=dim, input_resolution=input_resolution,\n                                 num_heads=num_heads, window_size=window_size,\n                                 shift_size=0 if (i % 2 == 0) else window_size // 2,\n                                 mlp_ratio=mlp_ratio,\n                                 qkv_bias=qkv_bias, qk_scale=qk_scale,\n                                 drop=drop, attn_drop=attn_drop,\n                                 drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,\n                                 norm_layer=norm_layer)\n            for i in range(depth)])\n\n        # patch merging layer\n        if downsample is not None:\n            self.downsample = downsample(input_resolution, dim=dim, norm_layer=norm_layer)\n        else:\n            self.downsample = None\n\n    def forward(self, x, condition=None):\n        for blk in self.blocks:\n            if self.use_checkpoint:\n                x = checkpoint.checkpoint(blk, x)\n            else:\n                x = blk(x, condition=condition)\n        if self.downsample is not None:\n            x = self.downsample(x)\n        return x\n\n    def extra_repr(self) -> str:\n        return f\"dim={self.dim}, input_resolution={self.input_resolution}, depth={self.depth}\"\n\n    def flops(self):\n        flops = 0\n        for blk in self.blocks:\n            flops += blk.flops()\n        if self.downsample is not None:\n            flops += self.downsample.flops()\n        return flops\n\n\nclass PatchEmbed(nn.Module):\n    r\"\"\" Image to Patch Embedding\n\n    Args:\n        img_size (int): Image size.  Default: 224.\n        patch_size (int): Patch token size. Default: 4.\n        in_chans (int): Number of input image channels. Default: 3.\n        embed_dim (int): Number of linear projection output channels. Default: 96.\n        norm_layer (nn.Module, optional): Normalization layer. Default: None\n    \"\"\"\n\n    def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):\n        super().__init__()\n        img_size = to_2tuple(img_size)\n        patch_size = to_2tuple(patch_size)\n        patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]\n        self.img_size = img_size\n        self.patch_size = patch_size\n        self.patches_resolution = patches_resolution\n        self.num_patches = patches_resolution[0] * patches_resolution[1]\n\n        self.in_chans = in_chans\n        self.embed_dim = embed_dim\n\n        self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)\n        if norm_layer is not None:\n            self.norm = norm_layer(embed_dim)\n        else:\n            self.norm = None\n\n    def forward(self, x):\n        B, C, H, W = x.shape\n        # FIXME look at relaxing size constraints\n        assert H == self.img_size[0] and W == self.img_size[1], \\\n            f\"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]}).\"\n        x = self.proj(x).flatten(2).transpose(1, 2)  # B Ph*Pw C\n        if self.norm is not None:\n            x = self.norm(x)\n        return x\n\n    def flops(self):\n        Ho, Wo = self.patches_resolution\n        flops = Ho * Wo * self.embed_dim * self.in_chans * (self.patch_size[0] * self.patch_size[1])\n        if self.norm is not None:\n            flops += Ho * Wo * self.embed_dim\n        return flops\n\n\nclass SwinTransformer(nn.Module):\n    r\"\"\" Swin Transformer\n        A PyTorch impl of : `Swin Transformer: Hierarchical Vision Transformer using Shifted Windows`  -\n          https://arxiv.org/pdf/2103.14030\n\n    Args:\n        img_size (int | tuple(int)): Input image size. Default 224\n        patch_size (int | tuple(int)): Patch size. Default: 4\n        in_chans (int): Number of input image channels. Default: 3\n        num_classes (int): Number of classes for classification head. Default: 1000\n        embed_dim (int): Patch embedding dimension. Default: 96\n        depths (tuple(int)): Depth of each Swin Transformer layer.\n        num_heads (tuple(int)): Number of attention heads in different layers.\n        window_size (int): Window size. Default: 7\n        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4\n        qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float): Override default qk scale of head_dim ** -0.5 if set. Default: None\n        drop_rate (float): Dropout rate. Default: 0\n        attn_drop_rate (float): Attention dropout rate. Default: 0\n        drop_path_rate (float): Stochastic depth rate. Default: 0.1\n        norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.\n        ape (bool): If True, add absolute position embedding to the patch embedding. Default: False\n        patch_norm (bool): If True, add normalization after patch embedding. Default: True\n        use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False\n    \"\"\"\n\n    def __init__(self, img_size=224, patch_size=4, in_chans=3, num_classes=1000,\n                 embed_dim=96, depths=[2, 2, 6, 2], num_heads=[3, 6, 12, 24],\n                 window_size=7, mlp_ratio=4., qkv_bias=True, qk_scale=None,\n                 drop_rate=0., attn_drop_rate=0., drop_path_rate=0.1,\n                 norm_layer=nn.LayerNorm, ape=False, patch_norm=True,\n                 use_checkpoint=False, **kwargs):\n        super().__init__()\n\n        self.num_classes = num_classes\n        self.num_layers = len(depths)\n        self.embed_dim = embed_dim\n        self.ape = ape\n        self.patch_norm = patch_norm\n        self.num_features = int(embed_dim * 2 ** (self.num_layers - 1))\n        self.mlp_ratio = mlp_ratio\n\n        # split image into non-overlapping patches\n        self.patch_embed = PatchEmbed(\n            img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim,\n            norm_layer=norm_layer if self.patch_norm else None)\n        num_patches = self.patch_embed.num_patches\n        patches_resolution = self.patch_embed.patches_resolution\n        self.patches_resolution = patches_resolution\n\n        # absolute position embedding\n        if self.ape:\n            self.absolute_pos_embed = nn.Parameter(torch.zeros(1, num_patches, embed_dim))\n            trunc_normal_(self.absolute_pos_embed, std=.02)\n\n        self.pos_drop = nn.Dropout(p=drop_rate)\n\n        # stochastic depth\n        dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))]  # stochastic depth decay rule\n\n        # build layers\n        self.layers = nn.ModuleList()\n        for i_layer in range(self.num_layers):\n            layer = BasicLayer(dim=int(embed_dim * 2 ** i_layer),\n                               input_resolution=(patches_resolution[0] // (2 ** i_layer),\n                                                 patches_resolution[1] // (2 ** i_layer)),\n                               depth=depths[i_layer],\n                               num_heads=num_heads[i_layer],\n                               window_size=window_size,\n                               mlp_ratio=self.mlp_ratio,\n                               qkv_bias=qkv_bias, qk_scale=qk_scale,\n                               drop=drop_rate, attn_drop=attn_drop_rate,\n                               drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])],\n                               norm_layer=norm_layer,\n                               downsample=PatchMerging if (i_layer < self.num_layers - 1) else None,\n                               use_checkpoint=use_checkpoint)\n            self.layers.append(layer)\n\n        self.norm = norm_layer(self.num_features)\n        self.avgpool = nn.AdaptiveAvgPool1d(1)\n        # self.head = nn.Linear(self.num_features, num_classes) if num_classes > 0 else nn.Identity()\n\n        self.apply(self._init_weights)\n\n    def _init_weights(self, m):\n        if isinstance(m, nn.Linear):\n            trunc_normal_(m.weight, std=.02)\n            if isinstance(m, nn.Linear) and m.bias is not None:\n                nn.init.constant_(m.bias, 0)\n        elif isinstance(m, nn.LayerNorm):\n            nn.init.constant_(m.bias, 0)\n            nn.init.constant_(m.weight, 1.0)\n\n    @torch.jit.ignore\n    def no_weight_decay(self):\n        return {'absolute_pos_embed'}\n\n    @torch.jit.ignore\n    def no_weight_decay_keywords(self):\n        return {'relative_position_bias_table'}\n\n    def forward(self, x, idx_to_group_img=None, image_atts=None, condition=None, **kwargs):\n        x = self.patch_embed(x)\n        if self.ape:\n            x = x + self.absolute_pos_embed\n        x = self.pos_drop(x)\n\n        for layer in self.layers:\n            x = layer(x, condition=condition)\n\n        x = self.norm(x)  # B L C\n\n        x_cls = self.avgpool(x.transpose(1, 2))  # B C 1\n\n        if idx_to_group_img is None:\n            return torch.cat([x_cls.transpose(1, 2), x], dim=1)\n        else:\n            x_bs = torch.gather(x, dim=0, index=idx_to_group_img.view(-1, 1, 1).expand(-1, x.shape[1], x.shape[2]))\n            weights = image_atts[:, 1:].unsqueeze(2)  # B L 1\n            x_bs_cls = torch.sum((weights * x_bs).transpose(1, 2), dim=-1, keepdim=True)   # B C 1\n            x_bs_cls = x_bs_cls / torch.sum(weights.transpose(1, 2), dim=-1, keepdim=True)  # avgpool\n\n            return torch.cat([x_bs_cls.transpose(1, 2), x_bs], dim=1), \\\n                   torch.cat([x_cls.transpose(1, 2), x], dim=1)\n\n    def flops(self):\n        flops = 0\n        flops += self.patch_embed.flops()\n        for i, layer in enumerate(self.layers):\n            flops += layer.flops()\n        flops += self.num_features * self.patches_resolution[0] * self.patches_resolution[1] // (2 ** self.num_layers)\n        flops += self.num_features * self.num_classes\n        return flops\n\n\ndef interpolate_relative_pos_embed(rel_pos_bias, dst_num_pos, param_name=''):\n    # from: https://github.com/microsoft/unilm/blob/8a0a1c1f4e7326938ea7580a00d56d7f17d65612/beit/run_class_finetuning.py#L348\n\n    # rel_pos_bias: relative_position_bias_table\n    src_num_pos, num_attn_heads = rel_pos_bias.size()\n\n    num_extra_tokens = 0\n    src_size = int((src_num_pos - num_extra_tokens) ** 0.5)\n    dst_size = int((dst_num_pos - num_extra_tokens) ** 0.5)\n    if src_size != dst_size:\n        print(\"Position interpolate %s from %dx%d to %dx%d\" % (param_name, src_size, src_size, dst_size, dst_size))\n\n        # extra_tokens = rel_pos_bias[-num_extra_tokens:, :]\n        # rel_pos_bias = rel_pos_bias[:-num_extra_tokens, :]\n\n        def geometric_progression(a, r, n):\n            return a * (1.0 - r ** n) / (1.0 - r)\n\n        left, right = 1.01, 1.5\n        while right - left > 1e-6:\n            q = (left + right) / 2.0\n            gp = geometric_progression(1, q, src_size // 2)\n            if gp > dst_size // 2:\n                right = q\n            else:\n                left = q\n\n        # if q > 1.090307:\n        #     q = 1.090307\n\n        dis = []\n        cur = 1\n        for i in range(src_size // 2):\n            dis.append(cur)\n            cur += q ** (i + 1)\n\n        r_ids = [-_ for _ in reversed(dis)]\n\n        x = r_ids + [0] + dis\n        y = r_ids + [0] + dis\n\n        t = dst_size // 2.0\n        dx = np.arange(-t, t + 0.1, 1.0)\n        dy = np.arange(-t, t + 0.1, 1.0)\n\n        # print(\"Original positions = %s\" % str(x))\n        # print(\"Target positions = %s\" % str(dx))\n\n        all_rel_pos_bias = []\n\n        for i in range(num_attn_heads):\n            z = rel_pos_bias[:, i].view(src_size, src_size).float().numpy()\n            f = interpolate.interp2d(x, y, z, kind='cubic')\n            all_rel_pos_bias.append(\n                torch.Tensor(f(dx, dy)).contiguous().view(-1, 1).to(rel_pos_bias.device))\n\n        rel_pos_bias = torch.cat(all_rel_pos_bias, dim=-1)\n\n    return rel_pos_bias\n\ndef zero_module(module):\n    for p in module.parameters():\n        nn.init.zeros_(p)\n    return module"
  },
  {
    "path": "ram/models/swin_transformer_lora.py",
    "content": "# --------------------------------------------------------\n# Swin Transformer\n# Copyright (c) 2021 Microsoft\n# Licensed under The MIT License [see LICENSE for details]\n# Written by Ze Liu\n# --------------------------------------------------------\n\nimport numpy as np\nfrom scipy import interpolate\n\nimport torch\nimport torch.nn as nn\nimport torch.utils.checkpoint as checkpoint\nfrom timm.models.layers import DropPath, to_2tuple, trunc_normal_\n\nimport loralib as lora\n\n\nclass Mlp(nn.Module):\n    def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):\n        super().__init__()\n        out_features = out_features or in_features\n        hidden_features = hidden_features or in_features\n        self.fc1 = nn.Linear(in_features, hidden_features)\n        # self.fc1 = lora.Linear(in_features, hidden_features, r=16)\n        self.act = act_layer()\n        self.fc2 = nn.Linear(hidden_features, out_features)\n        # self.fc2 = lora.Linear(hidden_features, out_features, r=16)\n        self.drop = nn.Dropout(drop)\n\n    def forward(self, x):\n        x = self.fc1(x)\n        x = self.act(x)\n        x = self.drop(x)\n        x = self.fc2(x)\n        x = self.drop(x)\n        return x\n\n\ndef window_partition(x, window_size):\n    \"\"\"\n    Args:\n        x: (B, H, W, C)\n        window_size (int): window size\n\n    Returns:\n        windows: (num_windows*B, window_size, window_size, C)\n    \"\"\"\n    B, H, W, C = x.shape\n    x = x.view(B, H // window_size, window_size, W // window_size, window_size, C)\n    windows = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, C)\n    return windows\n\n\ndef window_reverse(windows, window_size, H, W):\n    \"\"\"\n    Args:\n        windows: (num_windows*B, window_size, window_size, C)\n        window_size (int): Window size\n        H (int): Height of image\n        W (int): Width of image\n\n    Returns:\n        x: (B, H, W, C)\n    \"\"\"\n    B = int(windows.shape[0] / (H * W / window_size / window_size))\n    x = windows.view(B, H // window_size, W // window_size, window_size, window_size, -1)\n    x = x.permute(0, 1, 3, 2, 4, 5).contiguous().view(B, H, W, -1)\n    return x\n\n\nclass WindowAttention(nn.Module):\n    r\"\"\" Window based multi-head self attention (W-MSA) module with relative position bias.\n    It supports both of shifted and non-shifted window.\n\n    Args:\n        dim (int): Number of input channels.\n        window_size (tuple[int]): The height and width of the window.\n        num_heads (int): Number of attention heads.\n        qkv_bias (bool, optional):  If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set\n        attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0\n        proj_drop (float, optional): Dropout ratio of output. Default: 0.0\n    \"\"\"\n\n    def __init__(self, dim, window_size, num_heads, qkv_bias=True, qk_scale=None, attn_drop=0., proj_drop=0.):\n\n        super().__init__()\n        self.dim = dim\n        self.window_size = window_size  # Wh, Ww\n        self.num_heads = num_heads\n        head_dim = dim // num_heads\n        self.scale = qk_scale or head_dim ** -0.5\n\n        # define a parameter table of relative position bias\n        self.relative_position_bias_table = nn.Parameter(\n            torch.zeros((2 * window_size[0] - 1) * (2 * window_size[1] - 1), num_heads))  # 2*Wh-1 * 2*Ww-1, nH\n\n        # get pair-wise relative position index for each token inside the window\n        coords_h = torch.arange(self.window_size[0])\n        coords_w = torch.arange(self.window_size[1])\n        coords = torch.stack(torch.meshgrid([coords_h, coords_w]))  # 2, Wh, Ww\n        coords_flatten = torch.flatten(coords, 1)  # 2, Wh*Ww\n        relative_coords = coords_flatten[:, :, None] - coords_flatten[:, None, :]  # 2, Wh*Ww, Wh*Ww\n        relative_coords = relative_coords.permute(1, 2, 0).contiguous()  # Wh*Ww, Wh*Ww, 2\n        relative_coords[:, :, 0] += self.window_size[0] - 1  # shift to start from 0\n        relative_coords[:, :, 1] += self.window_size[1] - 1\n        relative_coords[:, :, 0] *= 2 * self.window_size[1] - 1\n        relative_position_index = relative_coords.sum(-1)  # Wh*Ww, Wh*Ww\n        self.register_buffer(\"relative_position_index\", relative_position_index)\n\n        # self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)\n        # lora version\n        self.qkv = lora.MergedLinear(dim, 3*dim, r=8, enable_lora=[True, False, True])\n        self.attn_drop = nn.Dropout(attn_drop)\n        self.proj = nn.Linear(dim, dim)\n        self.proj_drop = nn.Dropout(proj_drop)\n\n        trunc_normal_(self.relative_position_bias_table, std=.02)\n        self.softmax = nn.Softmax(dim=-1)\n\n    def forward(self, x, mask=None):\n        \"\"\"\n        Args:\n            x: input features with shape of (num_windows*B, N, C)\n            mask: (0/-inf) mask with shape of (num_windows, Wh*Ww, Wh*Ww) or None\n        \"\"\"\n        B_, N, C = x.shape\n        qkv = self.qkv(x).reshape(B_, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)\n        q, k, v = qkv[0], qkv[1], qkv[2]  # make torchscript happy (cannot use tensor as tuple)\n\n        q = q * self.scale\n        attn = (q @ k.transpose(-2, -1))\n\n        relative_position_bias = self.relative_position_bias_table[self.relative_position_index.view(-1)].view(\n            self.window_size[0] * self.window_size[1], self.window_size[0] * self.window_size[1], -1)  # Wh*Ww,Wh*Ww,nH\n        relative_position_bias = relative_position_bias.permute(2, 0, 1).contiguous()  # nH, Wh*Ww, Wh*Ww\n        attn = attn + relative_position_bias.unsqueeze(0)\n\n        if mask is not None:\n            nW = mask.shape[0]\n            attn = attn.view(B_ // nW, nW, self.num_heads, N, N) + mask.unsqueeze(1).unsqueeze(0)\n            attn = attn.view(-1, self.num_heads, N, N)\n            attn = self.softmax(attn)\n        else:\n            attn = self.softmax(attn)\n\n        attn = self.attn_drop(attn)\n\n        x = (attn @ v).transpose(1, 2).reshape(B_, N, C)\n        x = self.proj(x)\n        x = self.proj_drop(x)\n        return x\n\n    def extra_repr(self) -> str:\n        return f'dim={self.dim}, window_size={self.window_size}, num_heads={self.num_heads}'\n\n    def flops(self, N):\n        # calculate flops for 1 window with token length of N\n        flops = 0\n        # qkv = self.qkv(x)\n        flops += N * self.dim * 3 * self.dim\n        # attn = (q @ k.transpose(-2, -1))\n        flops += self.num_heads * N * (self.dim // self.num_heads) * N\n        #  x = (attn @ v)\n        flops += self.num_heads * N * N * (self.dim // self.num_heads)\n        # x = self.proj(x)\n        flops += N * self.dim * self.dim\n        return flops\n\n\nclass SwinTransformerBlock(nn.Module):\n    r\"\"\" Swin Transformer Block.\n\n    Args:\n        dim (int): Number of input channels.\n        input_resolution (tuple[int]): Input resulotion.\n        num_heads (int): Number of attention heads.\n        window_size (int): Window size.\n        shift_size (int): Shift size for SW-MSA.\n        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.\n        qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.\n        drop (float, optional): Dropout rate. Default: 0.0\n        attn_drop (float, optional): Attention dropout rate. Default: 0.0\n        drop_path (float, optional): Stochastic depth rate. Default: 0.0\n        act_layer (nn.Module, optional): Activation layer. Default: nn.GELU\n        norm_layer (nn.Module, optional): Normalization layer.  Default: nn.LayerNorm\n    \"\"\"\n\n    def __init__(self, dim, input_resolution, num_heads, window_size=7, shift_size=0,\n                 mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0., drop_path=0.,\n                 act_layer=nn.GELU, norm_layer=nn.LayerNorm):\n        super().__init__()\n        self.dim = dim\n        self.input_resolution = input_resolution\n        self.num_heads = num_heads\n        self.window_size = window_size\n        self.shift_size = shift_size\n        self.mlp_ratio = mlp_ratio\n        if min(self.input_resolution) <= self.window_size:\n            # if window size is larger than input resolution, we don't partition windows\n            self.shift_size = 0\n            self.window_size = min(self.input_resolution)\n        assert 0 <= self.shift_size < self.window_size, \"shift_size must in 0-window_size\"\n\n        self.norm1 = norm_layer(dim)\n        self.attn = WindowAttention(\n            dim, window_size=to_2tuple(self.window_size), num_heads=num_heads,\n            qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)\n\n        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()\n        self.norm2 = norm_layer(dim)\n        mlp_hidden_dim = int(dim * mlp_ratio)\n        self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)\n\n        if self.shift_size > 0:\n            # calculate attention mask for SW-MSA\n            H, W = self.input_resolution\n            img_mask = torch.zeros((1, H, W, 1))  # 1 H W 1\n            h_slices = (slice(0, -self.window_size),\n                        slice(-self.window_size, -self.shift_size),\n                        slice(-self.shift_size, None))\n            w_slices = (slice(0, -self.window_size),\n                        slice(-self.window_size, -self.shift_size),\n                        slice(-self.shift_size, None))\n            cnt = 0\n            for h in h_slices:\n                for w in w_slices:\n                    img_mask[:, h, w, :] = cnt\n                    cnt += 1\n\n            mask_windows = window_partition(img_mask, self.window_size)  # nW, window_size, window_size, 1\n            mask_windows = mask_windows.view(-1, self.window_size * self.window_size)\n            attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)\n            attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))\n        else:\n            attn_mask = None\n\n        self.register_buffer(\"attn_mask\", attn_mask)\n\n    def forward(self, x):\n        H, W = self.input_resolution\n        B, L, C = x.shape\n        assert L == H * W, \"input feature has wrong size\"\n\n        shortcut = x\n        x = self.norm1(x)\n        x = x.view(B, H, W, C)\n\n        # cyclic shift\n        if self.shift_size > 0:\n            shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))\n        else:\n            shifted_x = x\n\n        # partition windows\n        x_windows = window_partition(shifted_x, self.window_size)  # nW*B, window_size, window_size, C\n        x_windows = x_windows.view(-1, self.window_size * self.window_size, C)  # nW*B, window_size*window_size, C\n\n        # W-MSA/SW-MSA\n        attn_windows = self.attn(x_windows, mask=self.attn_mask)  # nW*B, window_size*window_size, C\n\n        # merge windows\n        attn_windows = attn_windows.view(-1, self.window_size, self.window_size, C)\n        shifted_x = window_reverse(attn_windows, self.window_size, H, W)  # B H' W' C\n\n        # reverse cyclic shift\n        if self.shift_size > 0:\n            x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))\n        else:\n            x = shifted_x\n        x = x.view(B, H * W, C)\n\n        # FFN\n        x = shortcut + self.drop_path(x)\n        x = x + self.drop_path(self.mlp(self.norm2(x)))\n\n        return x\n\n    def extra_repr(self) -> str:\n        return f\"dim={self.dim}, input_resolution={self.input_resolution}, num_heads={self.num_heads}, \" \\\n               f\"window_size={self.window_size}, shift_size={self.shift_size}, mlp_ratio={self.mlp_ratio}\"\n\n    def flops(self):\n        flops = 0\n        H, W = self.input_resolution\n        # norm1\n        flops += self.dim * H * W\n        # W-MSA/SW-MSA\n        nW = H * W / self.window_size / self.window_size\n        flops += nW * self.attn.flops(self.window_size * self.window_size)\n        # mlp\n        flops += 2 * H * W * self.dim * self.dim * self.mlp_ratio\n        # norm2\n        flops += self.dim * H * W\n        return flops\n\n\nclass PatchMerging(nn.Module):\n    r\"\"\" Patch Merging Layer.\n\n    Args:\n        input_resolution (tuple[int]): Resolution of input feature.\n        dim (int): Number of input channels.\n        norm_layer (nn.Module, optional): Normalization layer.  Default: nn.LayerNorm\n    \"\"\"\n\n    def __init__(self, input_resolution, dim, norm_layer=nn.LayerNorm):\n        super().__init__()\n        self.input_resolution = input_resolution\n        self.dim = dim\n        self.reduction = nn.Linear(4 * dim, 2 * dim, bias=False)\n        self.norm = norm_layer(4 * dim)\n\n    def forward(self, x):\n        \"\"\"\n        x: B, H*W, C\n        \"\"\"\n        H, W = self.input_resolution\n        B, L, C = x.shape\n        assert L == H * W, \"input feature has wrong size\"\n        assert H % 2 == 0 and W % 2 == 0, f\"x size ({H}*{W}) are not even.\"\n\n        x = x.view(B, H, W, C)\n\n        x0 = x[:, 0::2, 0::2, :]  # B H/2 W/2 C\n        x1 = x[:, 1::2, 0::2, :]  # B H/2 W/2 C\n        x2 = x[:, 0::2, 1::2, :]  # B H/2 W/2 C\n        x3 = x[:, 1::2, 1::2, :]  # B H/2 W/2 C\n        x = torch.cat([x0, x1, x2, x3], -1)  # B H/2 W/2 4*C\n        x = x.view(B, -1, 4 * C)  # B H/2*W/2 4*C\n\n        x = self.norm(x)\n        x = self.reduction(x)\n\n        return x\n\n    def extra_repr(self) -> str:\n        return f\"input_resolution={self.input_resolution}, dim={self.dim}\"\n\n    def flops(self):\n        H, W = self.input_resolution\n        flops = H * W * self.dim\n        flops += (H // 2) * (W // 2) * 4 * self.dim * 2 * self.dim\n        return flops\n\n\nclass BasicLayer(nn.Module):\n    \"\"\" A basic Swin Transformer layer for one stage.\n\n    Args:\n        dim (int): Number of input channels.\n        input_resolution (tuple[int]): Input resolution.\n        depth (int): Number of blocks.\n        num_heads (int): Number of attention heads.\n        window_size (int): Local window size.\n        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.\n        qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set.\n        drop (float, optional): Dropout rate. Default: 0.0\n        attn_drop (float, optional): Attention dropout rate. Default: 0.0\n        drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0\n        norm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm\n        downsample (nn.Module | None, optional): Downsample layer at the end of the layer. Default: None\n        use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False.\n    \"\"\"\n\n    def __init__(self, dim, input_resolution, depth, num_heads, window_size,\n                 mlp_ratio=4., qkv_bias=True, qk_scale=None, drop=0., attn_drop=0.,\n                 drop_path=0., norm_layer=nn.LayerNorm, downsample=None, use_checkpoint=False):\n\n        super().__init__()\n        self.dim = dim\n        self.input_resolution = input_resolution\n        self.depth = depth\n        self.use_checkpoint = use_checkpoint\n\n        # build blocks\n        self.blocks = nn.ModuleList([\n            SwinTransformerBlock(dim=dim, input_resolution=input_resolution,\n                                 num_heads=num_heads, window_size=window_size,\n                                 shift_size=0 if (i % 2 == 0) else window_size // 2,\n                                 mlp_ratio=mlp_ratio,\n                                 qkv_bias=qkv_bias, qk_scale=qk_scale,\n                                 drop=drop, attn_drop=attn_drop,\n                                 drop_path=drop_path[i] if isinstance(drop_path, list) else drop_path,\n                                 norm_layer=norm_layer)\n            for i in range(depth)])\n\n        # patch merging layer\n        if downsample is not None:\n            self.downsample = downsample(input_resolution, dim=dim, norm_layer=norm_layer)\n        else:\n            self.downsample = None\n\n    def forward(self, x):\n        for blk in self.blocks:\n            if self.use_checkpoint:\n                x = checkpoint.checkpoint(blk, x)\n            else:\n                x = blk(x)\n        if self.downsample is not None:\n            x = self.downsample(x)\n        return x\n\n    def extra_repr(self) -> str:\n        return f\"dim={self.dim}, input_resolution={self.input_resolution}, depth={self.depth}\"\n\n    def flops(self):\n        flops = 0\n        for blk in self.blocks:\n            flops += blk.flops()\n        if self.downsample is not None:\n            flops += self.downsample.flops()\n        return flops\n\n\nclass PatchEmbed(nn.Module):\n    r\"\"\" Image to Patch Embedding\n\n    Args:\n        img_size (int): Image size.  Default: 224.\n        patch_size (int): Patch token size. Default: 4.\n        in_chans (int): Number of input image channels. Default: 3.\n        embed_dim (int): Number of linear projection output channels. Default: 96.\n        norm_layer (nn.Module, optional): Normalization layer. Default: None\n    \"\"\"\n\n    def __init__(self, img_size=224, patch_size=4, in_chans=3, embed_dim=96, norm_layer=None):\n        super().__init__()\n        img_size = to_2tuple(img_size)\n        patch_size = to_2tuple(patch_size)\n        patches_resolution = [img_size[0] // patch_size[0], img_size[1] // patch_size[1]]\n        self.img_size = img_size\n        self.patch_size = patch_size\n        self.patches_resolution = patches_resolution\n        self.num_patches = patches_resolution[0] * patches_resolution[1]\n\n        self.in_chans = in_chans\n        self.embed_dim = embed_dim\n\n        self.proj = nn.Conv2d(in_chans, embed_dim, kernel_size=patch_size, stride=patch_size)\n        if norm_layer is not None:\n            self.norm = norm_layer(embed_dim)\n        else:\n            self.norm = None\n\n    def forward(self, x):\n        B, C, H, W = x.shape\n        # FIXME look at relaxing size constraints\n        assert H == self.img_size[0] and W == self.img_size[1], \\\n            f\"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]}).\"\n        x = self.proj(x).flatten(2).transpose(1, 2)  # B Ph*Pw C\n        if self.norm is not None:\n            x = self.norm(x)\n        return x\n\n    def flops(self):\n        Ho, Wo = self.patches_resolution\n        flops = Ho * Wo * self.embed_dim * self.in_chans * (self.patch_size[0] * self.patch_size[1])\n        if self.norm is not None:\n            flops += Ho * Wo * self.embed_dim\n        return flops\n\n\nclass SwinTransformer(nn.Module):\n    r\"\"\" Swin Transformer\n        A PyTorch impl of : `Swin Transformer: Hierarchical Vision Transformer using Shifted Windows`  -\n          https://arxiv.org/pdf/2103.14030\n\n    Args:\n        img_size (int | tuple(int)): Input image size. Default 224\n        patch_size (int | tuple(int)): Patch size. Default: 4\n        in_chans (int): Number of input image channels. Default: 3\n        num_classes (int): Number of classes for classification head. Default: 1000\n        embed_dim (int): Patch embedding dimension. Default: 96\n        depths (tuple(int)): Depth of each Swin Transformer layer.\n        num_heads (tuple(int)): Number of attention heads in different layers.\n        window_size (int): Window size. Default: 7\n        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4\n        qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: True\n        qk_scale (float): Override default qk scale of head_dim ** -0.5 if set. Default: None\n        drop_rate (float): Dropout rate. Default: 0\n        attn_drop_rate (float): Attention dropout rate. Default: 0\n        drop_path_rate (float): Stochastic depth rate. Default: 0.1\n        norm_layer (nn.Module): Normalization layer. Default: nn.LayerNorm.\n        ape (bool): If True, add absolute position embedding to the patch embedding. Default: False\n        patch_norm (bool): If True, add normalization after patch embedding. Default: True\n        use_checkpoint (bool): Whether to use checkpointing to save memory. Default: False\n    \"\"\"\n\n    def __init__(self, img_size=224, patch_size=4, in_chans=3, num_classes=1000,\n                 embed_dim=96, depths=[2, 2, 6, 2], num_heads=[3, 6, 12, 24],\n                 window_size=7, mlp_ratio=4., qkv_bias=True, qk_scale=None,\n                 drop_rate=0., attn_drop_rate=0., drop_path_rate=0.1,\n                 norm_layer=nn.LayerNorm, ape=False, patch_norm=True,\n                 use_checkpoint=False, **kwargs):\n        super().__init__()\n\n        self.num_classes = num_classes\n        self.num_layers = len(depths)\n        self.embed_dim = embed_dim\n        self.ape = ape\n        self.patch_norm = patch_norm\n        self.num_features = int(embed_dim * 2 ** (self.num_layers - 1))\n        self.mlp_ratio = mlp_ratio\n\n        # split image into non-overlapping patches\n        self.patch_embed = PatchEmbed(\n            img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim,\n            norm_layer=norm_layer if self.patch_norm else None)\n        num_patches = self.patch_embed.num_patches\n        patches_resolution = self.patch_embed.patches_resolution\n        self.patches_resolution = patches_resolution\n\n        # absolute position embedding\n        if self.ape:\n            self.absolute_pos_embed = nn.Parameter(torch.zeros(1, num_patches, embed_dim))\n            trunc_normal_(self.absolute_pos_embed, std=.02)\n\n        self.pos_drop = nn.Dropout(p=drop_rate)\n\n        # stochastic depth\n        dpr = [x.item() for x in torch.linspace(0, drop_path_rate, sum(depths))]  # stochastic depth decay rule\n\n        # build layers\n        self.layers = nn.ModuleList()\n        for i_layer in range(self.num_layers):\n            layer = BasicLayer(dim=int(embed_dim * 2 ** i_layer),\n                               input_resolution=(patches_resolution[0] // (2 ** i_layer),\n                                                 patches_resolution[1] // (2 ** i_layer)),\n                               depth=depths[i_layer],\n                               num_heads=num_heads[i_layer],\n                               window_size=window_size,\n                               mlp_ratio=self.mlp_ratio,\n                               qkv_bias=qkv_bias, qk_scale=qk_scale,\n                               drop=drop_rate, attn_drop=attn_drop_rate,\n                               drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])],\n                               norm_layer=norm_layer,\n                               downsample=PatchMerging if (i_layer < self.num_layers - 1) else None,\n                               use_checkpoint=use_checkpoint)\n            self.layers.append(layer)\n\n        self.norm = norm_layer(self.num_features)\n        self.avgpool = nn.AdaptiveAvgPool1d(1)\n        # self.head = nn.Linear(self.num_features, num_classes) if num_classes > 0 else nn.Identity()\n\n        self.apply(self._init_weights)\n\n    def _init_weights(self, m):\n        if isinstance(m, nn.Linear):\n            trunc_normal_(m.weight, std=.02)\n            if isinstance(m, nn.Linear) and m.bias is not None:\n                nn.init.constant_(m.bias, 0)\n        elif isinstance(m, nn.LayerNorm):\n            nn.init.constant_(m.bias, 0)\n            nn.init.constant_(m.weight, 1.0)\n\n    @torch.jit.ignore\n    def no_weight_decay(self):\n        return {'absolute_pos_embed'}\n\n    @torch.jit.ignore\n    def no_weight_decay_keywords(self):\n        return {'relative_position_bias_table'}\n\n    def forward(self, x, idx_to_group_img=None, image_atts=None, **kwargs):\n        x = self.patch_embed(x)\n        if self.ape:\n            x = x + self.absolute_pos_embed\n        x = self.pos_drop(x)\n\n        for layer in self.layers:\n            x = layer(x)\n\n        x = self.norm(x)  # B L C\n\n        x_cls = self.avgpool(x.transpose(1, 2))  # B C 1\n\n        if idx_to_group_img is None:\n            return torch.cat([x_cls.transpose(1, 2), x], dim=1)\n        else:\n            x_bs = torch.gather(x, dim=0, index=idx_to_group_img.view(-1, 1, 1).expand(-1, x.shape[1], x.shape[2]))\n            weights = image_atts[:, 1:].unsqueeze(2)  # B L 1\n            x_bs_cls = torch.sum((weights * x_bs).transpose(1, 2), dim=-1, keepdim=True)   # B C 1\n            x_bs_cls = x_bs_cls / torch.sum(weights.transpose(1, 2), dim=-1, keepdim=True)  # avgpool\n\n            return torch.cat([x_bs_cls.transpose(1, 2), x_bs], dim=1), \\\n                   torch.cat([x_cls.transpose(1, 2), x], dim=1)\n\n    def flops(self):\n        flops = 0\n        flops += self.patch_embed.flops()\n        for i, layer in enumerate(self.layers):\n            flops += layer.flops()\n        flops += self.num_features * self.patches_resolution[0] * self.patches_resolution[1] // (2 ** self.num_layers)\n        flops += self.num_features * self.num_classes\n        return flops\n\n\ndef interpolate_relative_pos_embed(rel_pos_bias, dst_num_pos, param_name=''):\n    # from: https://github.com/microsoft/unilm/blob/8a0a1c1f4e7326938ea7580a00d56d7f17d65612/beit/run_class_finetuning.py#L348\n\n    # rel_pos_bias: relative_position_bias_table\n    src_num_pos, num_attn_heads = rel_pos_bias.size()\n\n    num_extra_tokens = 0\n    src_size = int((src_num_pos - num_extra_tokens) ** 0.5)\n    dst_size = int((dst_num_pos - num_extra_tokens) ** 0.5)\n    if src_size != dst_size:\n        print(\"Position interpolate %s from %dx%d to %dx%d\" % (param_name, src_size, src_size, dst_size, dst_size))\n\n        # extra_tokens = rel_pos_bias[-num_extra_tokens:, :]\n        # rel_pos_bias = rel_pos_bias[:-num_extra_tokens, :]\n\n        def geometric_progression(a, r, n):\n            return a * (1.0 - r ** n) / (1.0 - r)\n\n        left, right = 1.01, 1.5\n        while right - left > 1e-6:\n            q = (left + right) / 2.0\n            gp = geometric_progression(1, q, src_size // 2)\n            if gp > dst_size // 2:\n                right = q\n            else:\n                left = q\n\n        # if q > 1.090307:\n        #     q = 1.090307\n\n        dis = []\n        cur = 1\n        for i in range(src_size // 2):\n            dis.append(cur)\n            cur += q ** (i + 1)\n\n        r_ids = [-_ for _ in reversed(dis)]\n\n        x = r_ids + [0] + dis\n        y = r_ids + [0] + dis\n\n        t = dst_size // 2.0\n        dx = np.arange(-t, t + 0.1, 1.0)\n        dy = np.arange(-t, t + 0.1, 1.0)\n\n        # print(\"Original positions = %s\" % str(x))\n        # print(\"Target positions = %s\" % str(dx))\n\n        all_rel_pos_bias = []\n\n        for i in range(num_attn_heads):\n            z = rel_pos_bias[:, i].view(src_size, src_size).float().numpy()\n            f = interpolate.interp2d(x, y, z, kind='cubic')\n            all_rel_pos_bias.append(\n                torch.Tensor(f(dx, dy)).contiguous().view(-1, 1).to(rel_pos_bias.device))\n\n        rel_pos_bias = torch.cat(all_rel_pos_bias, dim=-1)\n\n    return rel_pos_bias"
  },
  {
    "path": "ram/models/tag2text.py",
    "content": "'''\n * The Tag2Text Model\n * Written by Xinyu Huang\n'''\nimport numpy as np\nimport json\nimport torch\nimport warnings\n\nfrom torch import nn\nfrom .bert import BertConfig, BertModel, BertLMHeadModel\nfrom .swin_transformer import SwinTransformer\n\nfrom .utils import *\n\nwarnings.filterwarnings(\"ignore\")\n\n\nclass Tag2Text(nn.Module):\n\n    def __init__(self,\n                 med_config=f'{CONFIG_PATH}/configs/med_config.json',\n                 image_size=384,\n                 vit='base',\n                 vit_grad_ckpt=False,\n                 vit_ckpt_layer=0,\n                 prompt='a picture of ',\n                 threshold=0.68,\n                 delete_tag_index=[127,2961, 3351, 3265, 3338, 3355, 3359],\n                 tag_list=f'{CONFIG_PATH}/data/tag_list.txt'):\n        r\"\"\" Tag2Text inference module, both captioning and tagging are included.\n        Tag2Text is an efficient and controllable vision-language pre-training framework.\n        Described in the paper \"Tag2Text: Guiding Vision-Language Model via Image Tagging\" https://arxiv.org/abs/2303.05657\n\n        Args:\n            med_config (str): path for the mixture of encoder-decoder model's configuration file\n            image_size (int): input image size\n            vit (str): model size of vision transformer\n            threshold (int): tagging threshold\n            delete_tag_index (list): delete some tags that may disturb captioning\n        \"\"\"\n        super().__init__()\n\n        # create image encoder\n        if vit == 'swin_b':\n            if image_size == 224:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_224.json'\n            elif image_size == 384:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_384.json'\n            vision_config = read_json(vision_config_path)\n            assert image_size == vision_config['image_res']\n            # assert config['patch_size'] == 32\n            vision_width = vision_config['vision_width']\n\n            self.visual_encoder = SwinTransformer(\n                img_size=vision_config['image_res'],\n                patch_size=4,\n                in_chans=3,\n                embed_dim=vision_config['embed_dim'],\n                depths=vision_config['depths'],\n                num_heads=vision_config['num_heads'],\n                window_size=vision_config['window_size'],\n                mlp_ratio=4.,\n                qkv_bias=True,\n                drop_rate=0.0,\n                drop_path_rate=0.1,\n                ape=False,\n                patch_norm=True,\n                use_checkpoint=False)\n\n        else:\n            self.visual_encoder, vision_width = create_vit(\n                vit, image_size, vit_grad_ckpt, vit_ckpt_layer)\n\n        # create tokenzier\n        self.tokenizer = init_tokenizer()\n\n        # Tag2Text employ encoder-decoder architecture for image-tag-text generation: image-tag interaction encoder and image-tag-text decoder\n        # create image-tag interaction encoder\n        encoder_config = BertConfig.from_json_file(med_config)\n        encoder_config.encoder_width = vision_width\n        self.tag_encoder = BertModel(config=encoder_config,\n                                     add_pooling_layer=False)\n\n        # create image-tag-text decoder\n        decoder_config = BertConfig.from_json_file(med_config)\n        self.text_decoder = BertLMHeadModel(config=decoder_config)\n\n        # delete some tags that may disturb captioning\n        # 127: \"quarter\"; 2961: \"back\"; 3351: \"two\"; 3265: \"three\"; 3338: \"four\"; 3355: \"five\"; 3359: \"one\"\n        self.delete_tag_index = delete_tag_index\n        self.prompt = prompt\n        self.prompt_length = len(self.tokenizer(self.prompt).input_ids) - 1\n\n        # load tag list\n        self.tag_list = self.load_tag_list(tag_list)\n\n        # create image-tag recognition decoder\n        self.threshold = threshold\n        self.num_class = len(self.tag_list)\n        q2l_config = BertConfig.from_json_file(f'{CONFIG_PATH}/configs/q2l_config.json')\n        q2l_config.encoder_width = vision_width\n        self.tagging_head = BertModel(config=q2l_config,\n                                      add_pooling_layer=False)\n        self.tagging_head.resize_token_embeddings(len(self.tokenizer))\n        self.label_embed = nn.Embedding(self.num_class, q2l_config.hidden_size)\n        self.fc = GroupWiseLinear(self.num_class,\n                                  q2l_config.hidden_size,\n                                  bias=True)\n        self.del_selfattention()\n\n        self.tagging_loss_function = AsymmetricLoss(gamma_neg=7,\n                                                    gamma_pos=0,\n                                                    clip=0.05)\n\n        # share weights of the lowest 2-layer of \"image-tag interaction encoder\" with the \"image-tag recogntion decoder\"\n        tie_encoder_decoder_weights(self.tag_encoder, self.tagging_head, '',\n                                    ' ')\n\n        # adjust thresholds for some tags\n        # default threshold: 0.68\n        # 2701: \"person\"; 2828: \"man\"; 1167: \"woman\"; \n        tag_thrshold = {2701:0.7, 2828: 0.7, 1167: 0.7}\n        self.class_threshold = torch.ones(self.num_class) * self.threshold\n        for key,value in tag_thrshold.items():\n            self.class_threshold[key] = value\n\n    def load_tag_list(self, tag_list_file):\n        with open(tag_list_file, 'r') as f:\n            tag_list = f.read().splitlines()\n        tag_list = np.array(tag_list)\n        return tag_list\n\n    # delete self-attention layer of image-tag recognition decoder to reduce computation, follower Query2Label\n    def del_selfattention(self):\n        del self.tagging_head.embeddings\n        for layer in self.tagging_head.encoder.layer:\n            del layer.attention\n    \n\n    def forward(self, image, caption, tag):\n        \"\"\"\n        call function as forward\n\n        Args:\n            image: type: torch.Tensor  shape: batch_size * 3 * 384 * 384\n            caption: type: list[string]  len: batch_size\n            tag: type: torch.Tensor   shape: batch * class_num (e.g. 3429)   value: positive sample is 1.0, negative sample is 0.0\n\n        Returns:\n            loss: type: torch.Tensor\n        \"\"\"\n\n        image_embeds = self.visual_encoder(image)\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        ##================= Image Tagging ================##\n        bs = image_embeds.shape[0]\n        label_embed = self.label_embed.weight.unsqueeze(0).repeat(bs, 1, 1)\n\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0])\n\n        loss_tag = self.tagging_loss_function(logits, tag)\n\n        ##================= Image-Tag-Text Generation ================##\n        tag = tag.cpu().numpy()\n        tag_input = []\n        for b in range(bs):\n            index = np.argwhere(tag[b] == 1)\n            token = self.tag_list[index].squeeze(axis=1)\n            tag_input.append(' | '.join(token))\n        \n        # tokenizer input tags\n        tag_input_tokenzier = self.tokenizer(tag_input,\n                                             padding='max_length',\n                                             truncation=True,\n                                             max_length=40,\n                                             return_tensors=\"pt\").to(\n                                                 image.device)\n        encoder_input_ids = tag_input_tokenzier.input_ids\n        encoder_input_ids[:, 0] = self.tokenizer.enc_token_id\n\n        # put input tag into image-tag interaction encoder to interact with image embeddings\n        output_tagembedding = self.tag_encoder(\n            encoder_input_ids,\n            attention_mask=tag_input_tokenzier.attention_mask,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=True,\n        )\n\n        text = self.tokenizer(caption,\n                              padding='longest',\n                              truncation=True,\n                              max_length=40,\n                                return_tensors=\"pt\").to(\n                                    image.device)\n        \n        decoder_input_ids = text.input_ids\n        decoder_input_ids[:,0] = self.tokenizer.bos_token_id\n\n        decoder_targets = decoder_input_ids.masked_fill(\n            decoder_input_ids == self.tokenizer.pad_token_id, -100) \n        decoder_targets[:,:self.prompt_length] = -100\n        \n        decoder_output = self.text_decoder(decoder_input_ids, \n                                           attention_mask = text.attention_mask, \n                                           encoder_hidden_states = output_tagembedding.last_hidden_state,\n                                           encoder_attention_mask = None,                  \n                                           labels = decoder_targets,\n                                           return_dict = True,   \n                                          )   \n        \n        loss_t2t = decoder_output.loss\n\n        # balance loss scale\n        loss = loss_t2t + loss_tag/(loss_tag/loss_t2t).detach()\n\n        return loss\n\n    def generate_image_embeds(self,\n                 image,\n                 condition=False\n                 ):\n            \n        image_embeds = self.visual_encoder(image)\n        \n        return image_embeds\n\n    def condition_forward(self,\n                 image,\n                 sample=False,\n                 num_beams=3,\n                 max_length=30,\n                 min_length=10,\n                 top_p=0.9,\n                 repetition_penalty=1.0,\n                 tag_input=None,\n                 return_tag_predict=False):\n\n        image_embeds = self.visual_encoder(image)\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # if not user specified tags, recognized image tags using image-tag recogntiion decoder\n\n\n        bs = image_embeds.shape[0]\n        label_embed = self.label_embed.weight.unsqueeze(0).repeat(bs, 1, 1)\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0])\n\n        targets = torch.where(\n            torch.sigmoid(logits) > self.class_threshold.to(image.device),\n            torch.tensor(1.0).to(image.device),\n            torch.zeros(self.num_class).to(image.device))\n\n        # delete some tags that may disturb captioning\n        targets[:, self.delete_tag_index] = 0\n\n        return image_embeds, logits, targets\n\n\n    def generate(self,\n                 image,\n                 sample=False,\n                 num_beams=3,\n                 max_length=30,\n                 min_length=10,\n                 top_p=0.9,\n                 repetition_penalty=1.0,\n                 tag_input=None,\n                 return_tag_predict=False):\n\n        image_embeds = self.visual_encoder(image)\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # if not user specified tags, recognized image tags using image-tag recogntiion decoder\n        if tag_input == None:\n\n            bs = image_embeds.shape[0]\n            label_embed = self.label_embed.weight.unsqueeze(0).repeat(bs, 1, 1)\n            tagging_embed = self.tagging_head(\n                encoder_embeds=label_embed,\n                encoder_hidden_states=image_embeds,\n                encoder_attention_mask=image_atts,\n                return_dict=False,\n                mode='tagging',\n            )\n\n            logits = self.fc(tagging_embed[0])\n\n            targets = torch.where(\n                torch.sigmoid(logits) > self.class_threshold.to(image.device),\n                torch.tensor(1.0).to(image.device),\n                torch.zeros(self.num_class).to(image.device))\n\n            tag = targets.cpu().numpy()\n\n            # delete some tags that may disturb captioning\n            tag[:, self.delete_tag_index] = 0\n\n            tag_input = []\n            for b in range(bs):\n                index = np.argwhere(tag[b] == 1)\n                token = self.tag_list[index].squeeze(axis=1)\n                tag_input.append(', '.join(token))\n                \n        tag_output = tag_input\n\n        # beam search for text generation(default)\n        if not sample:\n            image_embeds = image_embeds.repeat_interleave(num_beams, dim=0)\n            tag_input_temp = []\n            for tag in tag_input:\n                for i in range(num_beams):\n                    tag_input_temp.append(tag)\n            tag_input = tag_input_temp\n\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # tokenizer input tags\n        tag_input_tokenzier = self.tokenizer(tag_input,\n                                             padding='max_length',\n                                             truncation=True,\n                                             max_length=40,\n                                             return_tensors=\"pt\").to(\n                                                 image.device)\n        encoder_input_ids = tag_input_tokenzier.input_ids\n        encoder_input_ids[:, 0] = self.tokenizer.enc_token_id\n\n        # put input tag into image-tag interaction encoder to interact with image embeddings\n        output_tagembedding = self.tag_encoder(\n            encoder_input_ids,\n            attention_mask=tag_input_tokenzier.attention_mask,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=True,\n        )\n\n        # prompt trick for better captioning, followed BLIP\n        prompt = [self.prompt] * image.size(0)\n        input_ids = self.tokenizer(prompt, return_tensors=\"pt\").input_ids.to(\n            image.device)\n        input_ids[:, 0] = self.tokenizer.bos_token_id\n        input_ids = input_ids[:, :-1]\n\n        if sample:\n            # nucleus sampling\n            model_kwargs = {\n                \"encoder_hidden_states\": output_tagembedding.last_hidden_state,\n                \"encoder_attention_mask\": None\n            }\n            outputs = self.text_decoder.generate(\n                input_ids=input_ids,\n                max_length=max_length,\n                min_length=min_length,\n                do_sample=True,\n                top_p=top_p,\n                num_return_sequences=1,\n                eos_token_id=self.tokenizer.sep_token_id,\n                pad_token_id=self.tokenizer.pad_token_id,\n                repetition_penalty=1.1,\n                **model_kwargs)\n        else:\n            # beam search (default)\n            model_kwargs = {\n                \"encoder_hidden_states\": output_tagembedding.last_hidden_state,\n                \"encoder_attention_mask\": None\n            }\n            outputs = self.text_decoder.generate(\n                input_ids=input_ids,\n                max_length=max_length,\n                min_length=min_length,\n                num_beams=num_beams,\n                eos_token_id=self.tokenizer.sep_token_id,\n                pad_token_id=self.tokenizer.pad_token_id,\n                repetition_penalty=repetition_penalty,\n                **model_kwargs)\n\n        captions = []\n        for output in outputs:\n            caption = self.tokenizer.decode(output, skip_special_tokens=True)\n            captions.append(caption[len(self.prompt):])\n        if return_tag_predict == True:\n            return  captions, tag_output\n        return captions\n\n\n# load Tag2Text pretrained model parameters\ndef tag2text(pretrained='', **kwargs):\n    model = Tag2Text(**kwargs)\n    if pretrained:\n        if kwargs['vit'] == 'swin_b':\n            model, msg = load_checkpoint_swinbase(model, pretrained, kwargs)\n        else:\n            model, msg = load_checkpoint(model, pretrained)\n        print('vit:', kwargs['vit'])\n#         print('msg', msg)\n    return model\n\n"
  },
  {
    "path": "ram/models/tag2text_lora.py",
    "content": "'''\n * The Tag2Text Model\n * Written by Xinyu Huang\n'''\nimport numpy as np\nimport json\nimport torch\nimport warnings\n\nfrom torch import nn\nfrom .bert_lora import BertConfig, BertModel, BertLMHeadModel\nfrom .swin_transformer_lora import SwinTransformer\n\nfrom .utils import *\n\nwarnings.filterwarnings(\"ignore\")\n\n\nclass Tag2Text(nn.Module):\n\n    def __init__(self,\n                 med_config=f'{CONFIG_PATH}/configs/med_config.json',\n                 image_size=384,\n                 vit='base',\n                 vit_grad_ckpt=False,\n                 vit_ckpt_layer=0,\n                 prompt='a picture of ',\n                 threshold=0.68,\n                 delete_tag_index=[127,2961, 3351, 3265, 3338, 3355, 3359],\n                 tag_list=f'{CONFIG_PATH}/data/tag_list.txt'):\n        r\"\"\" Tag2Text inference module, both captioning and tagging are included.\n        Tag2Text is an efficient and controllable vision-language pre-training framework.\n        Described in the paper \"Tag2Text: Guiding Vision-Language Model via Image Tagging\" https://arxiv.org/abs/2303.05657\n\n        Args:\n            med_config (str): path for the mixture of encoder-decoder model's configuration file\n            image_size (int): input image size\n            vit (str): model size of vision transformer\n            threshold (int): tagging threshold\n            delete_tag_index (list): delete some tags that may disturb captioning\n        \"\"\"\n        super().__init__()\n\n        # create image encoder\n        if vit == 'swin_b':\n            if image_size == 224:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_224.json'\n            elif image_size == 384:\n                vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_384.json'\n            vision_config = read_json(vision_config_path)\n            assert image_size == vision_config['image_res']\n            # assert config['patch_size'] == 32\n            vision_width = vision_config['vision_width']\n\n            self.visual_encoder = SwinTransformer(\n                img_size=vision_config['image_res'],\n                patch_size=4,\n                in_chans=3,\n                embed_dim=vision_config['embed_dim'],\n                depths=vision_config['depths'],\n                num_heads=vision_config['num_heads'],\n                window_size=vision_config['window_size'],\n                mlp_ratio=4.,\n                qkv_bias=True,\n                drop_rate=0.0,\n                drop_path_rate=0.1,\n                ape=False,\n                patch_norm=True,\n                use_checkpoint=False)\n\n        else:\n            self.visual_encoder, vision_width = create_vit(\n                vit, image_size, vit_grad_ckpt, vit_ckpt_layer)\n\n        # create tokenzier\n        self.tokenizer = init_tokenizer()\n\n        # Tag2Text employ encoder-decoder architecture for image-tag-text generation: image-tag interaction encoder and image-tag-text decoder\n        # create image-tag interaction encoder\n        encoder_config = BertConfig.from_json_file(med_config)\n        encoder_config.encoder_width = vision_width\n        self.tag_encoder = BertModel(config=encoder_config,\n                                     add_pooling_layer=False)\n\n        # create image-tag-text decoder\n        decoder_config = BertConfig.from_json_file(med_config)\n        self.text_decoder = BertLMHeadModel(config=decoder_config)\n\n        # delete some tags that may disturb captioning\n        # 127: \"quarter\"; 2961: \"back\"; 3351: \"two\"; 3265: \"three\"; 3338: \"four\"; 3355: \"five\"; 3359: \"one\"\n        self.delete_tag_index = delete_tag_index\n        self.prompt = prompt\n        self.prompt_length = len(self.tokenizer(self.prompt).input_ids) - 1\n\n        # load tag list\n        self.tag_list = self.load_tag_list(tag_list)\n\n        # create image-tag recognition decoder\n        self.threshold = threshold\n        self.num_class = len(self.tag_list)\n        q2l_config = BertConfig.from_json_file(f'{CONFIG_PATH}/configs/q2l_config.json')\n        q2l_config.encoder_width = vision_width\n        self.tagging_head = BertModel(config=q2l_config,\n                                      add_pooling_layer=False)\n        self.tagging_head.resize_token_embeddings(len(self.tokenizer))\n        self.label_embed = nn.Embedding(self.num_class, q2l_config.hidden_size)\n        self.fc = GroupWiseLinear(self.num_class,\n                                  q2l_config.hidden_size,\n                                  bias=True)\n        self.del_selfattention()\n\n        self.tagging_loss_function = AsymmetricLoss(gamma_neg=7,\n                                                    gamma_pos=0,\n                                                    clip=0.05)\n\n        # share weights of the lowest 2-layer of \"image-tag interaction encoder\" with the \"image-tag recogntion decoder\"\n        tie_encoder_decoder_weights(self.tag_encoder, self.tagging_head, '',\n                                    ' ')\n\n        # adjust thresholds for some tags\n        # default threshold: 0.68\n        # 2701: \"person\"; 2828: \"man\"; 1167: \"woman\"; \n        tag_thrshold = {2701:0.7, 2828: 0.7, 1167: 0.7}\n        self.class_threshold = torch.ones(self.num_class) * self.threshold\n        for key,value in tag_thrshold.items():\n            self.class_threshold[key] = value\n\n    def load_tag_list(self, tag_list_file):\n        with open(tag_list_file, 'r') as f:\n            tag_list = f.read().splitlines()\n        tag_list = np.array(tag_list)\n        return tag_list\n\n    # delete self-attention layer of image-tag recognition decoder to reduce computation, follower Query2Label\n    def del_selfattention(self):\n        del self.tagging_head.embeddings\n        for layer in self.tagging_head.encoder.layer:\n            del layer.attention\n    \n\n    def forward(self, image, caption, tag):\n        \"\"\"\n        call function as forward\n\n        Args:\n            image: type: torch.Tensor  shape: batch_size * 3 * 384 * 384\n            caption: type: list[string]  len: batch_size\n            tag: type: torch.Tensor   shape: batch * class_num (e.g. 3429)   value: positive sample is 1.0, negative sample is 0.0\n\n        Returns:\n            loss: type: torch.Tensor\n        \"\"\"\n\n        image_embeds = self.visual_encoder(image)\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        ##================= Image Tagging ================##\n        bs = image_embeds.shape[0]\n        label_embed = self.label_embed.weight.unsqueeze(0).repeat(bs, 1, 1)\n\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0])\n\n        loss_tag = self.tagging_loss_function(logits, tag)\n\n        ##================= Image-Tag-Text Generation ================##\n        tag = tag.cpu().numpy()\n        tag_input = []\n        for b in range(bs):\n            index = np.argwhere(tag[b] == 1)\n            token = self.tag_list[index].squeeze(axis=1)\n            tag_input.append(' | '.join(token))\n        \n        # tokenizer input tags\n        tag_input_tokenzier = self.tokenizer(tag_input,\n                                             padding='max_length',\n                                             truncation=True,\n                                             max_length=40,\n                                             return_tensors=\"pt\").to(\n                                                 image.device)\n        encoder_input_ids = tag_input_tokenzier.input_ids\n        encoder_input_ids[:, 0] = self.tokenizer.enc_token_id\n\n        # put input tag into image-tag interaction encoder to interact with image embeddings\n        output_tagembedding = self.tag_encoder(\n            encoder_input_ids,\n            attention_mask=tag_input_tokenzier.attention_mask,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=True,\n        )\n\n        text = self.tokenizer(caption,\n                              padding='longest',\n                              truncation=True,\n                              max_length=40,\n                                return_tensors=\"pt\").to(\n                                    image.device)\n        \n        decoder_input_ids = text.input_ids\n        decoder_input_ids[:,0] = self.tokenizer.bos_token_id\n\n        decoder_targets = decoder_input_ids.masked_fill(\n            decoder_input_ids == self.tokenizer.pad_token_id, -100) \n        decoder_targets[:,:self.prompt_length] = -100\n        \n        decoder_output = self.text_decoder(decoder_input_ids, \n                                           attention_mask = text.attention_mask, \n                                           encoder_hidden_states = output_tagembedding.last_hidden_state,\n                                           encoder_attention_mask = None,                  \n                                           labels = decoder_targets,\n                                           return_dict = True,   \n                                          )   \n        \n        loss_t2t = decoder_output.loss\n\n        # balance loss scale\n        loss = loss_t2t + loss_tag/(loss_tag/loss_t2t).detach()\n\n        return loss\n\n    def generate_image_embeds(self,\n                 image,\n                 condition=False\n                 ):\n            \n        image_embeds = self.visual_encoder(image)\n        \n        return image_embeds\n\n    def condition_forward(self,\n                 image,\n                 sample=False,\n                 num_beams=3,\n                 max_length=30,\n                 min_length=10,\n                 top_p=0.9,\n                 repetition_penalty=1.0,\n                 tag_input=None,\n                 return_tag_predict=False):\n\n        image_embeds = self.visual_encoder(image)\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # if not user specified tags, recognized image tags using image-tag recogntiion decoder\n\n\n        bs = image_embeds.shape[0]\n        label_embed = self.label_embed.weight.unsqueeze(0).repeat(bs, 1, 1)\n        tagging_embed = self.tagging_head(\n            encoder_embeds=label_embed,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=False,\n            mode='tagging',\n        )\n\n        logits = self.fc(tagging_embed[0])\n\n        targets = torch.where(\n            torch.sigmoid(logits) > self.class_threshold.to(image.device),\n            torch.tensor(1.0).to(image.device),\n            torch.zeros(self.num_class).to(image.device))\n\n        # delete some tags that may disturb captioning\n        targets[:, self.delete_tag_index] = 0\n\n        return image_embeds, logits, targets\n\n\n    def generate(self,\n                 image,\n                 sample=False,\n                 num_beams=3,\n                 max_length=30,\n                 min_length=10,\n                 top_p=0.9,\n                 repetition_penalty=1.0,\n                 tag_input=None,\n                 return_tag_predict=False):\n\n        image_embeds = self.visual_encoder(image)\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # if not user specified tags, recognized image tags using image-tag recogntiion decoder\n        if tag_input == None:\n\n            bs = image_embeds.shape[0]\n            label_embed = self.label_embed.weight.unsqueeze(0).repeat(bs, 1, 1)\n            tagging_embed = self.tagging_head(\n                encoder_embeds=label_embed,\n                encoder_hidden_states=image_embeds,\n                encoder_attention_mask=image_atts,\n                return_dict=False,\n                mode='tagging',\n            )\n\n            logits = self.fc(tagging_embed[0])\n\n            targets = torch.where(\n                torch.sigmoid(logits) > self.class_threshold.to(image.device),\n                torch.tensor(1.0).to(image.device),\n                torch.zeros(self.num_class).to(image.device))\n\n            tag = targets.cpu().numpy()\n\n            # delete some tags that may disturb captioning\n            tag[:, self.delete_tag_index] = 0\n\n            tag_input = []\n            for b in range(bs):\n                index = np.argwhere(tag[b] == 1)\n                token = self.tag_list[index].squeeze(axis=1)\n                tag_input.append(', '.join(token))\n                \n        tag_output = tag_input\n\n        # beam search for text generation(default)\n        if not sample:\n            image_embeds = image_embeds.repeat_interleave(num_beams, dim=0)\n            tag_input_temp = []\n            for tag in tag_input:\n                for i in range(num_beams):\n                    tag_input_temp.append(tag)\n            tag_input = tag_input_temp\n\n        image_atts = torch.ones(image_embeds.size()[:-1],\n                                dtype=torch.long).to(image.device)\n\n        # tokenizer input tags\n        tag_input_tokenzier = self.tokenizer(tag_input,\n                                             padding='max_length',\n                                             truncation=True,\n                                             max_length=40,\n                                             return_tensors=\"pt\").to(\n                                                 image.device)\n        encoder_input_ids = tag_input_tokenzier.input_ids\n        encoder_input_ids[:, 0] = self.tokenizer.enc_token_id\n\n        # put input tag into image-tag interaction encoder to interact with image embeddings\n        output_tagembedding = self.tag_encoder(\n            encoder_input_ids,\n            attention_mask=tag_input_tokenzier.attention_mask,\n            encoder_hidden_states=image_embeds,\n            encoder_attention_mask=image_atts,\n            return_dict=True,\n        )\n\n        # prompt trick for better captioning, followed BLIP\n        prompt = [self.prompt] * image.size(0)\n        input_ids = self.tokenizer(prompt, return_tensors=\"pt\").input_ids.to(\n            image.device)\n        input_ids[:, 0] = self.tokenizer.bos_token_id\n        input_ids = input_ids[:, :-1]\n\n        if sample:\n            # nucleus sampling\n            model_kwargs = {\n                \"encoder_hidden_states\": output_tagembedding.last_hidden_state,\n                \"encoder_attention_mask\": None\n            }\n            outputs = self.text_decoder.generate(\n                input_ids=input_ids,\n                max_length=max_length,\n                min_length=min_length,\n                do_sample=True,\n                top_p=top_p,\n                num_return_sequences=1,\n                eos_token_id=self.tokenizer.sep_token_id,\n                pad_token_id=self.tokenizer.pad_token_id,\n                repetition_penalty=1.1,\n                **model_kwargs)\n        else:\n            # beam search (default)\n            model_kwargs = {\n                \"encoder_hidden_states\": output_tagembedding.last_hidden_state,\n                \"encoder_attention_mask\": None\n            }\n            outputs = self.text_decoder.generate(\n                input_ids=input_ids,\n                max_length=max_length,\n                min_length=min_length,\n                num_beams=num_beams,\n                eos_token_id=self.tokenizer.sep_token_id,\n                pad_token_id=self.tokenizer.pad_token_id,\n                repetition_penalty=repetition_penalty,\n                **model_kwargs)\n\n        captions = []\n        for output in outputs:\n            caption = self.tokenizer.decode(output, skip_special_tokens=True)\n            captions.append(caption[len(self.prompt):])\n        if return_tag_predict == True:\n            return  captions, tag_output\n        return captions\n\n\n# load Tag2Text pretrained model parameters\ndef tag2text(pretrained='', **kwargs):\n    model = Tag2Text(**kwargs)\n    if pretrained:\n        if kwargs['vit'] == 'swin_b':\n            model, msg = load_checkpoint_swinbase(model, pretrained, kwargs)\n        else:\n            model, msg = load_checkpoint(model, pretrained)\n        print('vit:', kwargs['vit'])\n#         print('msg', msg)\n    return model\n\n"
  },
  {
    "path": "ram/models/utils.py",
    "content": "import os\nimport json\nimport torch\nimport math\n\nfrom torch import nn\nfrom typing import List\nfrom transformers import BertTokenizer\nfrom urllib.parse import urlparse\nfrom timm.models.hub import download_cached_file\nfrom .vit import interpolate_pos_embed\nfrom .swin_transformer import interpolate_relative_pos_embed\nfrom pathlib import Path\nCONFIG_PATH=(Path(__file__).resolve().parents[1])\n\ndef read_json(rpath):\n    with open(rpath, 'r') as f:\n        return json.load(f)\n\n\ndef tie_encoder_decoder_weights(encoder: nn.Module, decoder: nn.Module,\n                                base_model_prefix: str, skip_key: str):\n    uninitialized_encoder_weights: List[str] = []\n    if decoder.__class__ != encoder.__class__:\n        logger.info(\n            f\"{decoder.__class__} and {encoder.__class__} are not equal. In this case make sure that all encoder weights are correctly initialized.\"\n        )\n\n    def tie_encoder_to_decoder_recursively(\n        decoder_pointer: nn.Module,\n        encoder_pointer: nn.Module,\n        module_name: str,\n        uninitialized_encoder_weights: List[str],\n        skip_key: str,\n        depth=0,\n    ):\n        assert isinstance(decoder_pointer, nn.Module) and isinstance(\n            encoder_pointer, nn.Module\n        ), f\"{decoder_pointer} and {encoder_pointer} have to be of type torch.nn.Module\"\n        if hasattr(decoder_pointer, \"weight\") and skip_key not in module_name:\n            assert hasattr(encoder_pointer, \"weight\")\n            encoder_pointer.weight = decoder_pointer.weight\n            if hasattr(decoder_pointer, \"bias\"):\n                assert hasattr(encoder_pointer, \"bias\")\n                encoder_pointer.bias = decoder_pointer.bias\n            print(module_name + ' is tied')\n            return\n\n        encoder_modules = encoder_pointer._modules\n        decoder_modules = decoder_pointer._modules\n        if len(decoder_modules) > 0:\n            assert (\n                len(encoder_modules) > 0\n            ), f\"Encoder module {encoder_pointer} does not match decoder module {decoder_pointer}\"\n\n            all_encoder_weights = set([\n                module_name + \"/\" + sub_name\n                for sub_name in encoder_modules.keys()\n            ])\n            encoder_layer_pos = 0\n            for name, module in decoder_modules.items():\n                if name.isdigit():\n                    encoder_name = str(int(name) + encoder_layer_pos)\n                    decoder_name = name\n                    if not isinstance(\n                            decoder_modules[decoder_name],\n                            type(encoder_modules[encoder_name])) and len(\n                                encoder_modules) != len(decoder_modules):\n                        # this can happen if the name corresponds to the position in a list module list of layers\n                        # in this case the decoder has added a cross-attention that the encoder does not have\n                        # thus skip this step and subtract one layer pos from encoder\n                        encoder_layer_pos -= 1\n                        continue\n                elif name not in encoder_modules:\n                    continue\n                elif depth > 500:\n                    raise ValueError(\n                        \"Max depth of recursive function `tie_encoder_to_decoder` reached. It seems that there is a circular dependency between two or more `nn.Modules` of your model.\"\n                    )\n                else:\n                    decoder_name = encoder_name = name\n                tie_encoder_to_decoder_recursively(\n                    decoder_modules[decoder_name],\n                    encoder_modules[encoder_name],\n                    module_name + \"/\" + name,\n                    uninitialized_encoder_weights,\n                    skip_key,\n                    depth=depth + 1,\n                )\n                all_encoder_weights.remove(module_name + \"/\" + encoder_name)\n\n            uninitialized_encoder_weights += list(all_encoder_weights)\n\n    # tie weights recursively\n    tie_encoder_to_decoder_recursively(decoder, encoder, base_model_prefix,\n                                       uninitialized_encoder_weights, skip_key)\n\n\nclass GroupWiseLinear(nn.Module):\n    # could be changed to:\n    # output = torch.einsum('ijk,zjk->ij', x, self.W)\n    # or output = torch.einsum('ijk,jk->ij', x, self.W[0])\n    def __init__(self, num_class, hidden_dim, bias=True):\n        super().__init__()\n        self.num_class = num_class\n        self.hidden_dim = hidden_dim\n        self.bias = bias\n\n        self.W = nn.Parameter(torch.Tensor(1, num_class, hidden_dim))\n        if bias:\n            self.b = nn.Parameter(torch.Tensor(1, num_class))\n        self.reset_parameters()\n\n    def reset_parameters(self):\n        stdv = 1. / math.sqrt(self.W.size(2))\n        for i in range(self.num_class):\n            self.W[0][i].data.uniform_(-stdv, stdv)\n        if self.bias:\n            for i in range(self.num_class):\n                self.b[0][i].data.uniform_(-stdv, stdv)\n\n    def forward(self, x):\n        # x: B,K,d\n        x = (self.W * x).sum(-1)\n        if self.bias:\n            x = x + self.b\n        return x\n\n\ndef init_tokenizer():\n    tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')\n    tokenizer.add_special_tokens({'bos_token': '[DEC]'})\n    tokenizer.add_special_tokens({'additional_special_tokens': ['[ENC]']})\n    tokenizer.enc_token_id = tokenizer.additional_special_tokens_ids[0]\n    return tokenizer\n\n\ndef create_vit(vit,\n               image_size,\n               use_grad_checkpointing=False,\n               ckpt_layer=0,\n               drop_path_rate=0):\n\n    assert vit in ['base', 'large'], \"vit parameter must be base or large\"\n    if vit == 'base':\n        vision_width = 768\n        visual_encoder = VisionTransformer(\n            img_size=image_size,\n            patch_size=16,\n            embed_dim=vision_width,\n            depth=12,\n            num_heads=12,\n            use_grad_checkpointing=use_grad_checkpointing,\n            ckpt_layer=ckpt_layer,\n            drop_path_rate=0 or drop_path_rate)\n    elif vit == 'large':\n        vision_width = 1024\n        visual_encoder = VisionTransformer(\n            img_size=image_size,\n            patch_size=16,\n            embed_dim=vision_width,\n            depth=24,\n            num_heads=16,\n            use_grad_checkpointing=use_grad_checkpointing,\n            ckpt_layer=ckpt_layer,\n            drop_path_rate=0.1 or drop_path_rate)\n    return visual_encoder, vision_width\n\n\ndef is_url(url_or_filename):\n    parsed = urlparse(url_or_filename)\n    return parsed.scheme in (\"http\", \"https\")\n\n\ndef load_checkpoint(model, url_or_filename):\n    if is_url(url_or_filename):\n        cached_file = download_cached_file(url_or_filename,\n                                           check_hash=False,\n                                           progress=True)\n        checkpoint = torch.load(cached_file, map_location='cpu')\n    elif os.path.isfile(url_or_filename):\n        checkpoint = torch.load(url_or_filename, map_location='cpu')\n    else:\n        raise RuntimeError('checkpoint url or path is invalid')\n\n    state_dict = checkpoint['model']\n\n    state_dict['visual_encoder.pos_embed'] = interpolate_pos_embed(\n        state_dict['visual_encoder.pos_embed'], model.visual_encoder)\n    if 'visual_encoder_m.pos_embed' in model.state_dict().keys():\n        state_dict['visual_encoder_m.pos_embed'] = interpolate_pos_embed(\n            state_dict['visual_encoder_m.pos_embed'], model.visual_encoder_m)\n    for key in model.state_dict().keys():\n        if key in state_dict.keys():\n            if state_dict[key].shape != model.state_dict()[key].shape:\n                del state_dict[key]\n\n    msg = model.load_state_dict(state_dict, strict=False)\n    print('load checkpoint from %s' % url_or_filename)\n    return model, msg\n\n# def load_checkpoint_condition(model, url_or_filename):\ndef load_checkpoint_swinlarge_condition(model, url_or_filename, kwargs):\n    if kwargs['image_size'] == 224:\n        vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_224.json'\n    elif kwargs['image_size'] == 384:\n        vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_384.json'\n    window_size = read_json(vision_config_path)['window_size']\n    print('--------------')\n    print(url_or_filename)\n    print('--------------')\n    if is_url(url_or_filename):\n        cached_file = download_cached_file(url_or_filename,\n                                           check_hash=False,\n                                           progress=True)\n        checkpoint = torch.load(cached_file, map_location='cpu')\n    elif os.path.isfile(url_or_filename):\n        checkpoint = torch.load(url_or_filename, map_location='cpu')\n    else:\n        raise RuntimeError('checkpoint url or path is invalid')\n\n    state_dict = checkpoint['params']\n\n    for k in list(state_dict.keys()):\n        if 'relative_position_bias_table' in k:\n            dst_num_pos = (2 * window_size - 1)**2\n            state_dict[k] = interpolate_relative_pos_embed(state_dict[k],\n                                                           dst_num_pos,\n                                                           param_name=k)\n        elif ('relative_position_index' in k) or ('attn_mask' in k):\n            del state_dict[k]\n        elif \"vision_multi\" in k:\n            state_dict[k.replace(\"vision_multi\",\n                                 \"tagging_head\")] = state_dict.pop(k)\n\n    msg = model.load_state_dict(state_dict, strict=False)\n    print('load checkpoint from %s' % url_or_filename)\n    return model, msg\n\n\ndef load_checkpoint_swinbase(model, url_or_filename, kwargs):\n    if kwargs['image_size'] == 224:\n        vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_224.json'\n    elif kwargs['image_size'] == 384:\n        vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinB_384.json'\n    window_size = read_json(vision_config_path)['window_size']\n    print('--------------')\n    print(url_or_filename)\n    print('--------------')\n    if is_url(url_or_filename):\n        cached_file = download_cached_file(url_or_filename,\n                                           check_hash=False,\n                                           progress=True)\n        checkpoint = torch.load(cached_file, map_location='cpu')\n    elif os.path.isfile(url_or_filename):\n        checkpoint = torch.load(url_or_filename, map_location='cpu')\n    else:\n        raise RuntimeError('checkpoint url or path is invalid')\n\n    state_dict = checkpoint['model']\n\n    for k in list(state_dict.keys()):\n        if 'relative_position_bias_table' in k:\n            dst_num_pos = (2 * window_size - 1)**2\n            state_dict[k] = interpolate_relative_pos_embed(state_dict[k],\n                                                           dst_num_pos,\n                                                           param_name=k)\n        elif ('relative_position_index' in k) or ('attn_mask' in k):\n            del state_dict[k]\n        elif \"vision_multi\" in k:\n            state_dict[k.replace(\"vision_multi\",\n                                 \"tagging_head\")] = state_dict.pop(k)\n\n    msg = model.load_state_dict(state_dict, strict=False)\n    print('load checkpoint from %s' % url_or_filename)\n    return model, msg\n\n\ndef load_checkpoint_swinlarge(model, url_or_filename, kwargs):\n    if kwargs['image_size'] == 224:\n        vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_224.json'\n    elif kwargs['image_size'] == 384:\n        vision_config_path = f'{CONFIG_PATH}/configs/swin/config_swinL_384.json'\n    window_size = read_json(vision_config_path)['window_size']\n    print('--------------')\n    print(url_or_filename)\n    print('--------------')\n    if is_url(url_or_filename):\n        cached_file = download_cached_file(url_or_filename,\n                                           check_hash=False,\n                                           progress=True)\n        checkpoint = torch.load(cached_file, map_location='cpu')\n    elif os.path.isfile(url_or_filename):\n        checkpoint = torch.load(url_or_filename, map_location='cpu')\n    else:\n        raise RuntimeError('checkpoint url or path is invalid')\n\n    state_dict = checkpoint['model']\n\n    for k in list(state_dict.keys()):\n        if 'relative_position_bias_table' in k:\n            dst_num_pos = (2 * window_size - 1)**2\n            state_dict[k] = interpolate_relative_pos_embed(state_dict[k],\n                                                           dst_num_pos,\n                                                           param_name=k)\n        elif ('relative_position_index' in k) or ('attn_mask' in k):\n            del state_dict[k]\n        elif \"vision_multi\" in k:\n            state_dict[k.replace(\"vision_multi\",\n                                 \"tagging_head\")] = state_dict.pop(k)\n\n    msg = model.load_state_dict(state_dict, strict=False)\n    print('load checkpoint from %s' % url_or_filename)\n    return model, msg\n\n\n# Tagging loss function\n# copy from https://github.com/Alibaba-MIIL/ASL/blob/main/src/loss_functions/losses.py\nclass AsymmetricLoss(nn.Module):\n    def __init__(self, gamma_neg=4, gamma_pos=1, clip=0.05, eps=1e-8, disable_torch_grad_focal_loss=True):\n        super(AsymmetricLoss, self).__init__()\n\n        self.gamma_neg = gamma_neg\n        self.gamma_pos = gamma_pos\n        self.clip = clip\n        self.disable_torch_grad_focal_loss = disable_torch_grad_focal_loss\n        self.eps = eps\n\n    def forward(self, x, y):\n        \"\"\"\"\n        Parameters\n        ----------\n        x: input logits\n        y: targets (multi-label binarized vector)\n        \"\"\"\n\n        # Calculating Probabilities\n        x_sigmoid = torch.sigmoid(x)\n        xs_pos = x_sigmoid\n        xs_neg = 1 - x_sigmoid\n\n        # Asymmetric Clipping\n        if self.clip is not None and self.clip > 0:\n            xs_neg = (xs_neg + self.clip).clamp(max=1)\n\n        # Basic CE calculation\n        los_pos = y * torch.log(xs_pos.clamp(min=self.eps))\n        los_neg = (1 - y) * torch.log(xs_neg.clamp(min=self.eps))\n        loss = los_pos + los_neg\n\n        # Asymmetric Focusing\n        if self.gamma_neg > 0 or self.gamma_pos > 0:\n            if self.disable_torch_grad_focal_loss:\n                torch.set_grad_enabled(False)\n            pt0 = xs_pos * y\n            pt1 = xs_neg * (1 - y)  # pt = p if t > 0 else 1-p\n            pt = pt0 + pt1\n            one_sided_gamma = self.gamma_pos * y + self.gamma_neg * (1 - y)\n            one_sided_w = torch.pow(1 - pt, one_sided_gamma)\n            if self.disable_torch_grad_focal_loss:\n                torch.set_grad_enabled(True)\n            loss *= one_sided_w\n\n        return -loss.sum()"
  },
  {
    "path": "ram/models/vit.py",
    "content": "'''\n * Copyright (c) 2022, salesforce.com, inc.\n * All rights reserved.\n * SPDX-License-Identifier: BSD-3-Clause\n * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause\n * By Junnan Li\n * Based on timm code base\n * https://github.com/rwightman/pytorch-image-models/tree/master/timm\n'''\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom functools import partial\n\nfrom timm.models.vision_transformer import _cfg, PatchEmbed\nfrom timm.models.registry import register_model\nfrom timm.models.layers import trunc_normal_, DropPath\nfrom timm.models.helpers import named_apply, adapt_input_conv\n\nfrom fairscale.nn.checkpoint.checkpoint_activations import checkpoint_wrapper\n\nclass Mlp(nn.Module):\n    \"\"\" MLP as used in Vision Transformer, MLP-Mixer and related networks\n    \"\"\"\n    def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):\n        super().__init__()\n        out_features = out_features or in_features\n        hidden_features = hidden_features or in_features\n        self.fc1 = nn.Linear(in_features, hidden_features)\n        self.act = act_layer()\n        self.fc2 = nn.Linear(hidden_features, out_features)\n        self.drop = nn.Dropout(drop)\n\n    def forward(self, x):\n        x = self.fc1(x)\n        x = self.act(x)\n        x = self.drop(x)\n        x = self.fc2(x)\n        x = self.drop(x)\n        return x\n\n\nclass Attention(nn.Module):\n    def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0.):\n        super().__init__()\n        self.num_heads = num_heads\n        head_dim = dim // num_heads\n        # NOTE scale factor was wrong in my original version, can set manually to be compat with prev weights\n        self.scale = qk_scale or head_dim ** -0.5\n        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)\n        self.attn_drop = nn.Dropout(attn_drop)\n        self.proj = nn.Linear(dim, dim)\n        self.proj_drop = nn.Dropout(proj_drop)\n        self.attn_gradients = None\n        self.attention_map = None\n        \n    def save_attn_gradients(self, attn_gradients):\n        self.attn_gradients = attn_gradients\n        \n    def get_attn_gradients(self):\n        return self.attn_gradients\n    \n    def save_attention_map(self, attention_map):\n        self.attention_map = attention_map\n        \n    def get_attention_map(self):\n        return self.attention_map\n    \n    def forward(self, x, register_hook=False):\n        B, N, C = x.shape\n        qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)\n        q, k, v = qkv[0], qkv[1], qkv[2]   # make torchscript happy (cannot use tensor as tuple)\n\n        attn = (q @ k.transpose(-2, -1)) * self.scale\n        attn = attn.softmax(dim=-1)\n        attn = self.attn_drop(attn)\n                \n        if register_hook:\n            self.save_attention_map(attn)\n            attn.register_hook(self.save_attn_gradients)        \n\n        x = (attn @ v).transpose(1, 2).reshape(B, N, C)\n        x = self.proj(x)\n        x = self.proj_drop(x)\n        return x\n\n\nclass Block(nn.Module):\n\n    def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0.,\n                 drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm, use_grad_checkpointing=False):\n        super().__init__()\n        self.norm1 = norm_layer(dim)\n        self.attn = Attention(\n            dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)\n        # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here\n        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()\n        self.norm2 = norm_layer(dim)\n        mlp_hidden_dim = int(dim * mlp_ratio)\n        self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)\n\n        if use_grad_checkpointing:\n            self.attn = checkpoint_wrapper(self.attn)\n            self.mlp = checkpoint_wrapper(self.mlp)\n\n    def forward(self, x, register_hook=False):\n        x = x + self.drop_path(self.attn(self.norm1(x), register_hook=register_hook))\n        x = x + self.drop_path(self.mlp(self.norm2(x)))\n        return x\n\n    \nclass VisionTransformer(nn.Module):\n    \"\"\" Vision Transformer\n    A PyTorch impl of : `An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale`  -\n        https://arxiv.org/abs/2010.11929\n    \"\"\"\n    def __init__(self, img_size=224, patch_size=16, in_chans=3, num_classes=1000, embed_dim=768, depth=12,\n                 num_heads=12, mlp_ratio=4., qkv_bias=True, qk_scale=None, representation_size=None,\n                 drop_rate=0., attn_drop_rate=0., drop_path_rate=0., norm_layer=None, \n                 use_grad_checkpointing=False, ckpt_layer=0):\n        \"\"\"\n        Args:\n            img_size (int, tuple): input image size\n            patch_size (int, tuple): patch size\n            in_chans (int): number of input channels\n            num_classes (int): number of classes for classification head\n            embed_dim (int): embedding dimension\n            depth (int): depth of transformer\n            num_heads (int): number of attention heads\n            mlp_ratio (int): ratio of mlp hidden dim to embedding dim\n            qkv_bias (bool): enable bias for qkv if True\n            qk_scale (float): override default qk scale of head_dim ** -0.5 if set\n            representation_size (Optional[int]): enable and set representation layer (pre-logits) to this value if set\n            drop_rate (float): dropout rate\n            attn_drop_rate (float): attention dropout rate\n            drop_path_rate (float): stochastic depth rate\n            norm_layer: (nn.Module): normalization layer\n        \"\"\"\n        super().__init__()\n        self.num_features = self.embed_dim = embed_dim  # num_features for consistency with other models\n        norm_layer = norm_layer or partial(nn.LayerNorm, eps=1e-6)\n\n        self.patch_embed = PatchEmbed(\n            img_size=img_size, patch_size=patch_size, in_chans=in_chans, embed_dim=embed_dim)\n\n        num_patches = self.patch_embed.num_patches\n\n        self.cls_token = nn.Parameter(torch.zeros(1, 1, embed_dim))\n        self.pos_embed = nn.Parameter(torch.zeros(1, num_patches + 1, embed_dim))\n        self.pos_drop = nn.Dropout(p=drop_rate)\n\n        dpr = [x.item() for x in torch.linspace(0, drop_path_rate, depth)]  # stochastic depth decay rule\n        self.blocks = nn.ModuleList([\n            Block(\n                dim=embed_dim, num_heads=num_heads, mlp_ratio=mlp_ratio, qkv_bias=qkv_bias, qk_scale=qk_scale,\n                drop=drop_rate, attn_drop=attn_drop_rate, drop_path=dpr[i], norm_layer=norm_layer,\n                use_grad_checkpointing=(use_grad_checkpointing and i>=depth-ckpt_layer)\n            )\n            for i in range(depth)])\n        self.norm = norm_layer(embed_dim)\n\n        trunc_normal_(self.pos_embed, std=.02)\n        trunc_normal_(self.cls_token, std=.02)\n        self.apply(self._init_weights)\n\n    def _init_weights(self, m):\n        if isinstance(m, nn.Linear):\n            trunc_normal_(m.weight, std=.02)\n            if isinstance(m, nn.Linear) and m.bias is not None:\n                nn.init.constant_(m.bias, 0)\n        elif isinstance(m, nn.LayerNorm):\n            nn.init.constant_(m.bias, 0)\n            nn.init.constant_(m.weight, 1.0)\n\n    @torch.jit.ignore\n    def no_weight_decay(self):\n        return {'pos_embed', 'cls_token'}\n\n    def forward(self, x, register_blk=-1):\n        B = x.shape[0]\n        x = self.patch_embed(x)\n\n        cls_tokens = self.cls_token.expand(B, -1, -1)  # stole cls_tokens impl from Phil Wang, thanks\n        x = torch.cat((cls_tokens, x), dim=1)\n  \n        x = x + self.pos_embed[:,:x.size(1),:]\n        x = self.pos_drop(x)\n\n        for i,blk in enumerate(self.blocks):\n            x = blk(x, register_blk==i)\n        x = self.norm(x)\n        \n        return x\n\n    @torch.jit.ignore()\n    def load_pretrained(self, checkpoint_path, prefix=''):\n        _load_weights(self, checkpoint_path, prefix)\n        \n\n@torch.no_grad()\ndef _load_weights(model: VisionTransformer, checkpoint_path: str, prefix: str = ''):\n    \"\"\" Load weights from .npz checkpoints for official Google Brain Flax implementation\n    \"\"\"\n    import numpy as np\n\n    def _n2p(w, t=True):\n        if w.ndim == 4 and w.shape[0] == w.shape[1] == w.shape[2] == 1:\n            w = w.flatten()\n        if t:\n            if w.ndim == 4:\n                w = w.transpose([3, 2, 0, 1])\n            elif w.ndim == 3:\n                w = w.transpose([2, 0, 1])\n            elif w.ndim == 2:\n                w = w.transpose([1, 0])\n        return torch.from_numpy(w)\n\n    w = np.load(checkpoint_path)\n    if not prefix and 'opt/target/embedding/kernel' in w:\n        prefix = 'opt/target/'\n\n    if hasattr(model.patch_embed, 'backbone'):\n        # hybrid\n        backbone = model.patch_embed.backbone\n        stem_only = not hasattr(backbone, 'stem')\n        stem = backbone if stem_only else backbone.stem\n        stem.conv.weight.copy_(adapt_input_conv(stem.conv.weight.shape[1], _n2p(w[f'{prefix}conv_root/kernel'])))\n        stem.norm.weight.copy_(_n2p(w[f'{prefix}gn_root/scale']))\n        stem.norm.bias.copy_(_n2p(w[f'{prefix}gn_root/bias']))\n        if not stem_only:\n            for i, stage in enumerate(backbone.stages):\n                for j, block in enumerate(stage.blocks):\n                    bp = f'{prefix}block{i + 1}/unit{j + 1}/'\n                    for r in range(3):\n                        getattr(block, f'conv{r + 1}').weight.copy_(_n2p(w[f'{bp}conv{r + 1}/kernel']))\n                        getattr(block, f'norm{r + 1}').weight.copy_(_n2p(w[f'{bp}gn{r + 1}/scale']))\n                        getattr(block, f'norm{r + 1}').bias.copy_(_n2p(w[f'{bp}gn{r + 1}/bias']))\n                    if block.downsample is not None:\n                        block.downsample.conv.weight.copy_(_n2p(w[f'{bp}conv_proj/kernel']))\n                        block.downsample.norm.weight.copy_(_n2p(w[f'{bp}gn_proj/scale']))\n                        block.downsample.norm.bias.copy_(_n2p(w[f'{bp}gn_proj/bias']))\n        embed_conv_w = _n2p(w[f'{prefix}embedding/kernel'])\n    else:\n        embed_conv_w = adapt_input_conv(\n            model.patch_embed.proj.weight.shape[1], _n2p(w[f'{prefix}embedding/kernel']))\n    model.patch_embed.proj.weight.copy_(embed_conv_w)\n    model.patch_embed.proj.bias.copy_(_n2p(w[f'{prefix}embedding/bias']))\n    model.cls_token.copy_(_n2p(w[f'{prefix}cls'], t=False))\n    pos_embed_w = _n2p(w[f'{prefix}Transformer/posembed_input/pos_embedding'], t=False)\n    if pos_embed_w.shape != model.pos_embed.shape:\n        pos_embed_w = resize_pos_embed(  # resize pos embedding when different size from pretrained weights\n            pos_embed_w, model.pos_embed, getattr(model, 'num_tokens', 1), model.patch_embed.grid_size)\n    model.pos_embed.copy_(pos_embed_w)\n    model.norm.weight.copy_(_n2p(w[f'{prefix}Transformer/encoder_norm/scale']))\n    model.norm.bias.copy_(_n2p(w[f'{prefix}Transformer/encoder_norm/bias']))\n#     if isinstance(model.head, nn.Linear) and model.head.bias.shape[0] == w[f'{prefix}head/bias'].shape[-1]:\n#         model.head.weight.copy_(_n2p(w[f'{prefix}head/kernel']))\n#         model.head.bias.copy_(_n2p(w[f'{prefix}head/bias']))\n#     if isinstance(getattr(model.pre_logits, 'fc', None), nn.Linear) and f'{prefix}pre_logits/bias' in w:\n#         model.pre_logits.fc.weight.copy_(_n2p(w[f'{prefix}pre_logits/kernel']))\n#         model.pre_logits.fc.bias.copy_(_n2p(w[f'{prefix}pre_logits/bias']))\n    for i, block in enumerate(model.blocks.children()):\n        block_prefix = f'{prefix}Transformer/encoderblock_{i}/'\n        mha_prefix = block_prefix + 'MultiHeadDotProductAttention_1/'\n        block.norm1.weight.copy_(_n2p(w[f'{block_prefix}LayerNorm_0/scale']))\n        block.norm1.bias.copy_(_n2p(w[f'{block_prefix}LayerNorm_0/bias']))\n        block.attn.qkv.weight.copy_(torch.cat([\n            _n2p(w[f'{mha_prefix}{n}/kernel'], t=False).flatten(1).T for n in ('query', 'key', 'value')]))\n        block.attn.qkv.bias.copy_(torch.cat([\n            _n2p(w[f'{mha_prefix}{n}/bias'], t=False).reshape(-1) for n in ('query', 'key', 'value')]))\n        block.attn.proj.weight.copy_(_n2p(w[f'{mha_prefix}out/kernel']).flatten(1))\n        block.attn.proj.bias.copy_(_n2p(w[f'{mha_prefix}out/bias']))\n        for r in range(2):\n            getattr(block.mlp, f'fc{r + 1}').weight.copy_(_n2p(w[f'{block_prefix}MlpBlock_3/Dense_{r}/kernel']))\n            getattr(block.mlp, f'fc{r + 1}').bias.copy_(_n2p(w[f'{block_prefix}MlpBlock_3/Dense_{r}/bias']))\n        block.norm2.weight.copy_(_n2p(w[f'{block_prefix}LayerNorm_2/scale']))\n        block.norm2.bias.copy_(_n2p(w[f'{block_prefix}LayerNorm_2/bias']))\n\n            \ndef interpolate_pos_embed(pos_embed_checkpoint, visual_encoder):        \n    # interpolate position embedding\n    embedding_size = pos_embed_checkpoint.shape[-1]\n    num_patches = visual_encoder.patch_embed.num_patches\n    num_extra_tokens = visual_encoder.pos_embed.shape[-2] - num_patches\n    # height (== width) for the checkpoint position embedding\n    orig_size = int((pos_embed_checkpoint.shape[-2] - num_extra_tokens) ** 0.5)\n    # height (== width) for the new position embedding\n    new_size = int(num_patches ** 0.5)\n\n    if orig_size!=new_size:\n        # class_token and dist_token are kept unchanged\n        extra_tokens = pos_embed_checkpoint[:, :num_extra_tokens]\n        # only the position tokens are interpolated\n        pos_tokens = pos_embed_checkpoint[:, num_extra_tokens:]\n        pos_tokens = pos_tokens.reshape(-1, orig_size, orig_size, embedding_size).permute(0, 3, 1, 2)\n        pos_tokens = torch.nn.functional.interpolate(\n            pos_tokens, size=(new_size, new_size), mode='bicubic', align_corners=False)\n        pos_tokens = pos_tokens.permute(0, 2, 3, 1).flatten(1, 2)\n        new_pos_embed = torch.cat((extra_tokens, pos_tokens), dim=1)\n        print('reshape position embedding from %d to %d'%(orig_size ** 2,new_size ** 2))\n        \n        return new_pos_embed    \n    else:\n        return pos_embed_checkpoint"
  },
  {
    "path": "requirements.txt",
    "content": "pillow==9.1.1\r\nopencv-python-headless==4.11.0.86\r\ntqdm==4.65.2\r\nomegaconf==2.3.0\r\ntorch==2.4.1\r\ntorchvision==0.19.1\r\ntorchaudio==2.4.1\r\nxformers==0.0.28.post1\r\nfairscale==0.4.13\r\nloralib==0.1.2\r\ntimm==0.9.16\r\npyiqa==0.1.13\r\ntransformers==4.37.2\r\ndiffusers==0.32.2\r\npeft==0.13.2\r\npytorch-lightning==2.4.0\r\n"
  },
  {
    "path": "test.py",
    "content": "import torch, os, glob, copy\nimport torch.nn.functional as F\nimport numpy as np\nfrom PIL import Image\nfrom argparse import ArgumentParser\nfrom torchvision import transforms\nfrom model import Net\n\nparser = ArgumentParser()\nparser.add_argument(\"--epoch\", type=int, default=200)\nparser.add_argument(\"--model_dir\", type=str, default=\"weight\")\nparser.add_argument(\"--LR_dir\", type=str, default=\"testset/RealSR/LR\")\nparser.add_argument(\"--HR_dir\", type=str, default=\"testset/RealSR/HR\")\nparser.add_argument(\"--SR_dir\", type=str, default=\"result/RealSR\")\nargs = parser.parse_args()\n\ndevice = torch.device(\"cuda\")\n\nfrom diffusers import StableDiffusionPipeline\nmodel_id = \"stabilityai/stable-diffusion-2-1-base\"\npipe = StableDiffusionPipeline.from_pretrained(model_id).to(device)\n\nvae = pipe.vae\ntokenizer = pipe.tokenizer\nunet = pipe.unet\nnoise_scheduler = pipe.scheduler\ntext_encoder = pipe.text_encoder\n\nfrom diffusers.models.autoencoders.vae import Decoder \nckpt_halfdecoder = torch.load(\"./weight/pretrained/halfDecoder.ckpt\", weights_only=False)\ndecoder = Decoder(in_channels=4,\n            out_channels=3,\n            up_block_types=[\"UpDecoderBlock2D\" for _ in range(4)],\n            block_out_channels=[64, 128, 256, 256],\n            layers_per_block=2, \n            norm_num_groups=32, \n            act_fn=\"silu\", \n            norm_type=\"group\", \n            mid_block_add_attention=True).to(device)\ndecoder_ckpt = {}\nfor k,v in ckpt_halfdecoder[\"state_dict\"].items():\n    if \"decoder\" in k:\n        new_k = k.replace(\"decoder.\", \"\")\n        decoder_ckpt[new_k] = v\ndecoder.load_state_dict(decoder_ckpt, strict=True)\n\nmodel = torch.nn.DataParallel(Net(unet, copy.deepcopy(decoder)))\nmodel.load_state_dict(torch.load(\"./%s/net_params_%d.pkl\" % (args.model_dir, args.epoch), weights_only=False))\nmodel = torch.nn.Sequential(\n    model.module,\n    *decoder.up_blocks,\n    decoder.conv_norm_out,\n    decoder.conv_act,\n    decoder.conv_out,\n).to(device)\n\ntest_LR_paths = list(sorted(glob.glob(os.path.join(args.LR_dir, \"*.png\"))))\ntest_HR_paths = list(sorted(glob.glob(os.path.join(args.HR_dir, \"*.png\"))))\n\nos.makedirs(args.SR_dir, exist_ok=True)\n\nwith torch.no_grad():\n    for i, path in enumerate(test_LR_paths):\n        LR = Image.open(path).convert(\"RGB\")\n        LR = transforms.ToTensor()(LR).to(device).unsqueeze(0) * 2 - 1\n        SR = model(LR)\n        SR = (SR - SR.mean(dim=[2,3],keepdim=True)) / SR.std(dim=[2,3],keepdim=True) \\\n             * LR.std(dim=[2,3],keepdim=True) + LR.mean(dim=[2,3],keepdim=True)\n        SR = transforms.ToPILImage()((SR[0] / 2 + 0.5).clamp(0, 1).cpu())\n        SR.save(os.path.join(args.SR_dir, os.path.basename(path)))\n"
  },
  {
    "path": "test_debug.sh",
    "content": "HF_ENDPOINT=https://hf-mirror.com \\\nCUDA_VISIBLE_DEVICES=0 \\\npython -u test.py \\\n--epoch=200 \\\n--LR_dir=testset/RealSR/LR \\\n--SR_dir=result/RealSR"
  },
  {
    "path": "train.py",
    "content": "import torch, os, glob, random, copy\nimport torch.nn.functional as F\nfrom torch.utils.data import DataLoader\nimport torch.distributed as dist\nfrom torch.nn.parallel import DistributedDataParallel as DDP\nimport numpy as np\nfrom argparse import ArgumentParser\nfrom time import time\nfrom tqdm import tqdm\nfrom omegaconf import OmegaConf\nfrom dataset import RealESRGANDataset, RealESRGANDegrader\nfrom model import Net\nfrom ram.models.ram_lora import ram\nfrom torchvision import transforms\nfrom utils import add_lora_to_unet\n\ndist.init_process_group(backend=\"nccl\", init_method=\"env://\")\nrank = dist.get_rank()\nworld_size = dist.get_world_size()\n\nparser = ArgumentParser()\nparser.add_argument(\"--epoch\", type=int, default=200)\nparser.add_argument(\"--batch_size\", type=int, default=12)\nparser.add_argument(\"--learning_rate\", type=float, default=1e-4)\nparser.add_argument(\"--model_dir\", type=str, default=\"weight\")\nparser.add_argument(\"--log_dir\", type=str, default=\"log\")\nparser.add_argument(\"--save_interval\", type=int, default=10)\n\nargs = parser.parse_args()\n\n# fixed seed for reproduction\nseed = rank\nrandom.seed(seed)\nnp.random.seed(seed)\ntorch.manual_seed(seed)\ntorch.cuda.manual_seed_all(seed)\n\nconfig = OmegaConf.load(\"config.yml\")\n\nepoch = args.epoch\nlearning_rate = args.learning_rate\nbsz = args.batch_size\n\ndevice = torch.device(f\"cuda:{rank}\" if torch.cuda.is_available() else \"cpu\")\ntorch.backends.cudnn.allow_tf32 = True\ntorch.backends.cuda.matmul.allow_tf32 = True\n\nif rank == 0:\n    print(\"batch size per gpu =\", bsz)\n\nfrom diffusers import StableDiffusionPipeline\nmodel_id = \"stabilityai/stable-diffusion-2-1-base\"\npipe = StableDiffusionPipeline.from_pretrained(model_id).to(device)\n\nvae = pipe.vae\ntokenizer = pipe.tokenizer\nunet = pipe.unet\ntext_encoder = pipe.text_encoder\n\nunet_D = copy.deepcopy(unet)\nnew_conv_in = torch.nn.Conv2d(256, 320, 3, padding=1).to(device)\nnew_conv_in.weight.data = unet_D.conv_in.weight.data.repeat(1, 64, 1, 1) / 64\nnew_conv_in.bias.data = unet_D.conv_in.bias.data\nunet_D.conv_in = new_conv_in\nunet_D = add_lora_to_unet(unet_D)\nunet_D.set_adapters([\"default_encoder\", \"default_decoder\", \"default_others\"])\n\nvae_teacher = copy.deepcopy(vae)\nunet_teacher = copy.deepcopy(unet)\n\nosediff = torch.load(\"./weight/pretrained/osediff.pkl\", weights_only=False)\nvae_teacher.load_state_dict(osediff[\"vae\"])\nunet_teacher.load_state_dict(osediff[\"unet\"])\n\nfrom diffusers.models.autoencoders.vae import Decoder \nckpt_halfdecoder = torch.load(\"./weight/pretrained/halfDecoder.ckpt\", weights_only=False)\ndecoder = Decoder(in_channels=4,\n                  out_channels=3,\n                  up_block_types=[\"UpDecoderBlock2D\" for _ in range(4)],\n                  block_out_channels=[64, 128, 256, 256],\n                  layers_per_block=2,\n                  norm_num_groups=32,\n                  act_fn=\"silu\",\n                  norm_type=\"group\",\n                  mid_block_add_attention=True).to(device)\ndecoder_ckpt = {}\nfor k, v in ckpt_halfdecoder[\"state_dict\"].items():\n    if \"decoder\" in k:\n        new_k = k.replace(\"decoder.\", \"\")\n        decoder_ckpt[new_k] = v\ndecoder.load_state_dict(decoder_ckpt, strict=True)\n\nram_transforms = transforms.Compose([\n    transforms.Resize((384, 384)),\n    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n])\n\nDAPE = ram(pretrained=\"./weight/pretrained/ram_swin_large_14m.pth\",\n           pretrained_condition=\"./weight/pretrained/DAPE.pth\",\n           image_size=384,\n           vit=\"swin_l\").eval().to(device)\n\nvae.requires_grad_(False)\nunet.requires_grad_(False)\ntext_encoder.requires_grad_(False)\nvae_teacher.requires_grad_(False)\nunet_teacher.requires_grad_(False)\ndecoder.requires_grad_(False)\nDAPE.requires_grad_(False)\n\nmodel = DDP(Net(unet, copy.deepcopy(decoder)).to(device), device_ids=[rank])\nmodel_D = DDP(unet_D.to(device), device_ids=[rank])\nmodel.requires_grad_(True)\nmodel_D.requires_grad_(False)\nparams_to_opt = []\nfor n, p in model_D.named_parameters():\n    if \"lora\" in n or \"conv_in\" in n:\n        p.requires_grad = True\n        params_to_opt.append(p)\n\nif rank == 0:\n    param_cnt = sum(p.numel() for p in model.parameters() if p.requires_grad)\n    print(\"#Param.\", param_cnt/1e6, \"M\")\n\ndataset = RealESRGANDataset(config, bsz)\ndegrader = RealESRGANDegrader(config, device)\ndataloader = DataLoader(dataset, batch_size=bsz, num_workers=8)\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\noptimizer_D = torch.optim.Adam(params_to_opt, lr=1e-6)\nscheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[100,], gamma=0.5)\nscaler = torch.cuda.amp.GradScaler()\n\nmodel_dir = \"./%s\" % (args.model_dir,)\nlog_path = \"./%s/log.txt\" % (args.log_dir,)\nos.makedirs(model_dir, exist_ok=True)\nos.makedirs(args.log_dir, exist_ok=True)\n\nprint(\"start training...\")\ntimesteps = torch.tensor([999], device=device).long().expand(bsz,)\nalpha = pipe.scheduler.alphas_cumprod[999]\nfor epoch_i in range(1, epoch + 1):\n    start_time = time()\n    loss_avg = 0.0\n    loss_distil_avg = 0.0\n    loss_adv_avg = 0.0\n    loss_D_avg = 0.0\n    iter_num = 0\n    dist.barrier()\n    for batch in tqdm(dataloader):\n        with torch.cuda.amp.autocast(enabled=True):\n            with torch.no_grad():\n                LR, HR = degrader.degrade(batch)\n                text_input = tokenizer(DAPE.generate_tag(ram_transforms(LR))[0],\n                                       max_length=tokenizer.model_max_length,\n                                       padding=\"max_length\", return_tensors=\"pt\").to(device)\n                encoder_hidden_states = text_encoder(text_input.input_ids, return_dict=False)[0]\n                LR, HR = LR * 2 - 1, HR * 2 - 1\n                LR_ = F.interpolate(LR, scale_factor=4, mode=\"bicubic\")\n                LR_latents = vae_teacher.encode(LR_).latent_dist.mean * vae_teacher.config.scaling_factor\n                HR_latents = vae.encode(HR).latent_dist.mean\n                pred_teacher = unet_teacher(\n                    LR_latents,\n                    timesteps,\n                    encoder_hidden_states=encoder_hidden_states,\n                    return_dict=False,\n                )[0]\n                z0_teacher = (LR_latents-((1-alpha)**0.5)*pred_teacher)/(alpha**0.5)\n                z0_teacher = vae_teacher.post_quant_conv(z0_teacher / vae_teacher.config.scaling_factor)\n                z0_teacher = decoder.conv_in(z0_teacher)\n                z0_teacher = decoder.mid_block(z0_teacher)\n                z0_gt = vae.post_quant_conv(HR_latents)\n                z0_gt = decoder.conv_in(z0_gt)\n                z0_gt = decoder.mid_block(z0_gt)\n            z0_student = model(LR)\n            loss_distil = (z0_student - z0_teacher).abs().mean()\n            loss_adv = F.softplus(-model_D(\n                z0_student,\n                timesteps,\n                encoder_hidden_states=encoder_hidden_states,\n                return_dict=False,\n            )[0]).mean()\n            loss = loss_distil + loss_adv\n        optimizer.zero_grad(set_to_none=True)\n        scaler.scale(loss).backward()\n        scaler.step(optimizer)\n        scaler.update()\n        with torch.cuda.amp.autocast(enabled=True):\n            pred_real = model_D(\n                z0_gt.detach(),\n                timesteps,\n                encoder_hidden_states=encoder_hidden_states,\n                return_dict=False,\n            )[0]\n            pred_fake = model_D(\n                z0_student.detach(),\n                timesteps,\n                encoder_hidden_states=encoder_hidden_states,\n                return_dict=False,\n            )[0]\n            loss_D = F.softplus(pred_fake).mean() + F.softplus(-pred_real).mean()\n        optimizer_D.zero_grad(set_to_none=True)\n        scaler.scale(loss_D).backward()\n        scaler.step(optimizer_D)\n        scaler.update()\n        loss_avg += loss.item()\n        loss_distil_avg += loss_distil.item()\n        loss_adv_avg += loss_adv.item()\n        loss_D_avg += loss_D.item()\n        iter_num += 1\n        # print(\"loss\", loss.item())\n        # print(\"loss_distil\", loss_distil.item())\n        # print(\"loss_adv\", loss_adv.item())\n        # print(\"loss_D\", loss_D.item())\n    scheduler.step()\n    loss_avg /= iter_num\n    loss_distil_avg /= iter_num\n    loss_adv_avg /= iter_num\n    loss_D_avg /= iter_num\n    log_data = \"[%d/%d] Average loss: %f, distil loss: %f, adv loss: %f, D loss: %f, time cost: %.2fs, cur lr is %f.\" % (epoch_i, epoch, loss_avg, loss_distil_avg, loss_adv_avg, loss_D_avg, time() - start_time, scheduler.get_last_lr()[0])\n    if rank == 0:\n        print(log_data)\n        with open(log_path, \"a\") as log_file:\n            log_file.write(log_data + \"\\n\")\n        if epoch_i % args.save_interval == 0:\n            torch.save(model.state_dict(), \"./%s/net_params_%d.pkl\" % (model_dir, epoch_i))\n"
  },
  {
    "path": "train.sh",
    "content": "HF_ENDPOINT=https://hf-mirror.com \\\nCUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 \\\npython -m torch.distributed.run \\\n--nproc_per_node=8 \\\n--master_port=23333 \\\ntrain.py > g0-7.txt 2>&1"
  },
  {
    "path": "train_debug.sh",
    "content": "HF_ENDPOINT=https://hf-mirror.com \\\nCUDA_VISIBLE_DEVICES=0 \\\nnohup torchrun \\\n--nproc_per_node=1 \\\n--master_port=23333 \\\ntrain.py \\\n--batch_size=1 > g0.txt 2>&1 &"
  },
  {
    "path": "utils.py",
    "content": "import torch\nfrom peft import LoraConfig\n\ndef add_lora_to_unet(unet, rank=4):\n    l_target_modules_encoder, l_target_modules_decoder, l_modules_others = [], [], []\n    l_grep = [\"to_k\", \"to_q\", \"to_v\", \"to_out.0\", \"conv\", \"conv1\", \"conv2\", \"conv_shortcut\", \"conv_out\", \"proj_out\", \"proj_in\", \"ff.net.2\", \"ff.net.0.proj\"]\n    for n, p in unet.named_parameters():\n        check_flag = 0\n        if \"bias\" in n or \"norm\" in n:\n            continue\n        for pattern in l_grep:\n            if pattern in n and (\"down_blocks\" in n or \"conv_in\" in n):\n                l_target_modules_encoder.append(n.replace(\".weight\",\"\"))\n                break\n            elif pattern in n and (\"up_blocks\" in n or \"conv_out\" in n):\n                l_target_modules_decoder.append(n.replace(\".weight\",\"\"))\n                break\n            elif pattern in n:\n                l_modules_others.append(n.replace(\".weight\",\"\"))\n                break\n    unet.add_adapter(LoraConfig(r=rank,init_lora_weights=\"gaussian\",target_modules=l_target_modules_encoder), adapter_name=\"default_encoder\")\n    unet.add_adapter(LoraConfig(r=rank,init_lora_weights=\"gaussian\",target_modules=l_target_modules_decoder), adapter_name=\"default_decoder\")\n    unet.add_adapter(LoraConfig(r=rank,init_lora_weights=\"gaussian\",target_modules=l_modules_others), adapter_name=\"default_others\")\n    return unet"
  }
]