sunhill commited on
Commit
6cd6130
·
1 Parent(s): 32cb5ae

temporary commit

Browse files
Files changed (4) hide show
  1. .gitignore +219 -0
  2. app.py +31 -3
  3. clip_score.py +57 -54
  4. requirements.txt +2 -1
.gitignore ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+
204
+ # Ruff stuff:
205
+ .ruff_cache/
206
+
207
+ # PyPI configuration file
208
+ .pypirc
209
+
210
+ # Marimo
211
+ marimo/_static/
212
+ marimo/_lsp/
213
+ __marimo__/
214
+
215
+ # Streamlit
216
+ .streamlit/secrets.toml
217
+
218
+ # VS Code
219
+ .vscode/
app.py CHANGED
@@ -1,6 +1,34 @@
1
  import evaluate
2
- from evaluate.utils import launch_gradio_widget
3
 
4
 
5
- module = evaluate.load("sunhill/clip_score")
6
- launch_gradio_widget(module)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import evaluate
2
+ import gradio as gr
3
 
4
 
5
+ metric = evaluate.load("clip_score.py")
6
+
7
+
8
+ def compute_clip_score(image, text):
9
+ results = metric.compute(predictions=[text], images=[image])
10
+ return results["clip_score"]
11
+
12
+
13
+ iface = gr.Interface(
14
+ fn=compute_clip_score,
15
+ inputs=[
16
+ gr.Image(type="pil"),
17
+ gr.Textbox(lines=2, placeholder="Enter text here..."),
18
+ ],
19
+ outputs=gr.Number(label="CLIP Score"),
20
+ title="CLIP Score Evaluator",
21
+ description="Evaluate the alignment between an image and a text using CLIP Score.",
22
+ examples=[
23
+ [
24
+ "https://images.unsplash.com/photo-1720539222585-346e73f01536",
25
+ "A cat sitting on a couch.",
26
+ ],
27
+ [
28
+ "https://images.unsplash.com/photo-1694253987647-4eebcf679974",
29
+ "A scenic view of mountains during sunset.",
30
+ ],
31
+ ],
32
+ )
33
+
34
+ iface.launch()
clip_score.py CHANGED
@@ -1,68 +1,58 @@
1
- # Copyright 2020 The HuggingFace Datasets Authors and the current dataset script contributor.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
- """TODO: Add a description here."""
15
 
16
  import evaluate
17
  import datasets
 
 
18
 
 
19
 
20
- # TODO: Add BibTeX citation
21
  _CITATION = """\
22
- @InProceedings{huggingface:module,
23
- title = {A great new module},
24
- authors={huggingface, Inc.},
25
- year={2020}
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
  """
28
 
29
- # TODO: Add description of the module here
30
  _DESCRIPTION = """\
31
- This new module is designed to solve this great ML task and is crafted with a lot of care.
32
  """
33
 
34
 
35
- # TODO: Add description of the arguments of the module here
36
  _KWARGS_DESCRIPTION = """
37
- Calculates how good are predictions given some references, using certain scores
38
  Args:
39
- predictions: list of predictions to score. Each predictions
40
- should be a string with tokens separated by spaces.
41
- references: list of reference for each prediction. Each
42
- reference should be a string with tokens separated by spaces.
43
  Returns:
44
- accuracy: description of the first score,
45
- another_score: description of the second score,
46
  Examples:
47
- Examples should be written in doctest format, and should illustrate how
48
- to use the function.
49
-
50
- >>> my_new_module = evaluate.load("my_new_module")
51
- >>> results = my_new_module.compute(references=[0, 1], predictions=[0, 1])
52
  >>> print(results)
53
- {'accuracy': 1.0}
54
  """
55
 
56
- # TODO: Define external resources urls if needed
57
- BAD_WORDS_URL = "http://url/to/external/resource/bad_words.txt"
58
-
59
 
60
  @evaluate.utils.file_utils.add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)
61
  class CLIPScore(evaluate.Metric):
62
- """TODO: Short description of my evaluation module."""
63
 
64
  def _info(self):
65
- # TODO: Specifies the evaluate.EvaluationModuleInfo object
66
  return evaluate.MetricInfo(
67
  # This is the description that will appear on the modules page.
68
  module_type="metric",
@@ -70,26 +60,39 @@ class CLIPScore(evaluate.Metric):
70
  citation=_CITATION,
71
  inputs_description=_KWARGS_DESCRIPTION,
72
  # This defines the format of each prediction and reference
73
- features=datasets.Features({
74
- 'predictions': datasets.Value('int64'),
75
- 'references': datasets.Value('int64'),
76
- }),
 
 
77
  # Homepage of the module for documentation
78
- homepage="http://module.homepage",
79
  # Additional links to the codebase or references
80
- codebase_urls=["http://github.com/path/to/codebase/of/new_module"],
81
- reference_urls=["http://path.to.reference.url/new_module"]
82
  )
83
 
84
  def _download_and_prepare(self, dl_manager):
85
  """Optional: download external resources useful to compute the scores"""
86
- # TODO: Download external resources if needed
87
- pass
 
 
88
 
89
  def _compute(self, predictions, references):
90
  """Returns the scores"""
91
- # TODO: Compute the different scores of the module
92
- accuracy = sum(i == j for i, j in zip(predictions, references)) / len(predictions)
93
- return {
94
- "accuracy": accuracy,
95
- }
 
 
 
 
 
 
 
 
 
 
1
+ """This module calculates CLIPScore, a reference-free evaluation metric for image captioning."""
 
 
 
 
 
 
 
 
 
 
 
 
 
2
 
3
  import evaluate
4
  import datasets
5
+ from evaluate.utils.logging import get_logger
6
+ from transformers import CLIPProcessor, CLIPModel, AutoTokenizer
7
 
8
+ logger = get_logger(__name__)
9
 
 
10
  _CITATION = """\
11
+ @article{DBLP:journals/corr/abs-2104-08718,
12
+ author = {Jack Hessel and
13
+ Ari Holtzman and
14
+ Maxwell Forbes and
15
+ Ronan Le Bras and
16
+ Yejin Choi},
17
+ title = {CLIPScore: {A} Reference-free Evaluation Metric for Image Captioning},
18
+ journal = {CoRR},
19
+ volume = {abs/2104.08718},
20
+ year = {2021},
21
+ url = {https://arxiv.org/abs/2104.08718},
22
+ eprinttype = {arXiv},
23
+ eprint = {2104.08718},
24
+ timestamp = {Sat, 29 Apr 2023 10:09:27 +0200},
25
+ biburl = {https://dblp.org/rec/journals/corr/abs-2104-08718.bib},
26
+ bibsource = {dblp computer science bibliography, https://dblp.org}
27
  }
28
  """
29
 
 
30
  _DESCRIPTION = """\
31
+ This new module is designed to calculate CLIPScore, a reference-free evaluation metric for image captioning.
32
  """
33
 
34
 
 
35
  _KWARGS_DESCRIPTION = """
36
+ Computes CLIPScore to evaluate the alignment between an image and a text.
37
  Args:
38
+ predictions: list of text predictions to score. Each prediction
39
+ should be a string.
40
+ images: list of images to score against. Each image should be a PIL image.
 
41
  Returns:
42
+ clip_score: CLIPScore between the image and the text.
 
43
  Examples:
44
+ >>> metric = evaluate.load("sunhill/clip_score")
45
+ >>> results = metric.compute(predictions=["A cat sitting on a couch."], images=[PIL_image])
 
 
 
46
  >>> print(results)
47
+ {'clip_score': 0.2076}
48
  """
49
 
 
 
 
50
 
51
  @evaluate.utils.file_utils.add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)
52
  class CLIPScore(evaluate.Metric):
53
+ """CLIPScore metric."""
54
 
55
  def _info(self):
 
56
  return evaluate.MetricInfo(
57
  # This is the description that will appear on the modules page.
58
  module_type="metric",
 
60
  citation=_CITATION,
61
  inputs_description=_KWARGS_DESCRIPTION,
62
  # This defines the format of each prediction and reference
63
+ features=datasets.Features(
64
+ {
65
+ "predictions": datasets.Value("string"),
66
+ "references": datasets.Value("float32"),
67
+ }
68
+ ),
69
  # Homepage of the module for documentation
70
+ homepage="https://huggingface.co/spaces/sunhill/clip_score",
71
  # Additional links to the codebase or references
72
+ codebase_urls=["https://github.com/Taited/clip-score"],
73
+ reference_urls=["https://arxiv.org/abs/2104.08718"],
74
  )
75
 
76
  def _download_and_prepare(self, dl_manager):
77
  """Optional: download external resources useful to compute the scores"""
78
+ logger.info("Downloading and preparing CLIP ViT-B/32 model...")
79
+ self.model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")
80
+ self.processor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")
81
+ self.tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
82
 
83
  def _compute(self, predictions, references):
84
  """Returns the scores"""
85
+ refer = self.processor(
86
+ text=None, images=references, return_tensors="pt", padding=True
87
+ )
88
+ refer["pixel_values"] = refer["pixel_values"][0]
89
+ pred = self.tokenizer(predictions, return_tensors="pt", padding=True)
90
+ for key in pred:
91
+ pred[key] = pred[key].squeeze()
92
+
93
+ refer_features = self.model.get_image_features(**refer)
94
+ pred_features = self.model.get_text_features(**pred)
95
+
96
+ refer_features = refer_features / refer_features.norm(dim=1, keepdim=True)
97
+ pred_features = pred_features / pred_features.norm(dim=1, keepdim=True)
98
+ return {"clip_score": (refer_features * pred_features).sum().item()}
requirements.txt CHANGED
@@ -1 +1,2 @@
1
- git+https://github.com/huggingface/evaluate@main
 
 
1
+ git+https://github.com/huggingface/evaluate@main
2
+ transformers