Jinglong Xiong commited on
Commit
15369ca
Β·
0 Parent(s):

first commit

Browse files
.gitignore ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.parquet
2
+ *.pth
3
+
4
+ # Byte-compiled / optimized / DLL files
5
+ __pycache__/
6
+ *.py[cod]
7
+ *$py.class
8
+
9
+ # C extensions
10
+ *.so
11
+
12
+ # Distribution / packaging
13
+ .Python
14
+ build/
15
+ develop-eggs/
16
+ dist/
17
+ downloads/
18
+ eggs/
19
+ .eggs/
20
+ lib/
21
+ lib64/
22
+ parts/
23
+ sdist/
24
+ var/
25
+ wheels/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+ cover/
56
+
57
+ # Translations
58
+ *.mo
59
+ *.pot
60
+
61
+ # Django stuff:
62
+ *.log
63
+ local_settings.py
64
+ db.sqlite3
65
+ db.sqlite3-journal
66
+
67
+ # Flask stuff:
68
+ instance/
69
+ .webassets-cache
70
+
71
+ # Scrapy stuff:
72
+ .scrapy
73
+
74
+ # Sphinx documentation
75
+ docs/_build/
76
+
77
+ # PyBuilder
78
+ .pybuilder/
79
+ target/
80
+
81
+ # Jupyter Notebook
82
+ .ipynb_checkpoints
83
+
84
+ # IPython
85
+ profile_default/
86
+ ipython_config.py
87
+
88
+ # pyenv
89
+ # For a library or package, you might want to ignore these files since the code is
90
+ # intended to run in multiple environments; otherwise, check them in:
91
+ # .python-version
92
+
93
+ # pipenv
94
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
95
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
96
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
97
+ # install all needed dependencies.
98
+ #Pipfile.lock
99
+
100
+ # UV
101
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
102
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
103
+ # commonly ignored for libraries.
104
+ #uv.lock
105
+
106
+ # poetry
107
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
108
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
109
+ # commonly ignored for libraries.
110
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
111
+ #poetry.lock
112
+
113
+ # pdm
114
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
115
+ #pdm.lock
116
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
117
+ # in version control.
118
+ # https://pdm.fming.dev/latest/usage/project/#working-with-version-control
119
+ .pdm.toml
120
+ .pdm-python
121
+ .pdm-build/
122
+
123
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
124
+ __pypackages__/
125
+
126
+ # Celery stuff
127
+ celerybeat-schedule
128
+ celerybeat.pid
129
+
130
+ # SageMath parsed files
131
+ *.sage.py
132
+
133
+ # Environments
134
+ .env
135
+ .venv
136
+ env/
137
+ venv/
138
+ ENV/
139
+ env.bak/
140
+ venv.bak/
141
+
142
+ # Spyder project settings
143
+ .spyderproject
144
+ .spyproject
145
+
146
+ # Rope project settings
147
+ .ropeproject
148
+
149
+ # mkdocs documentation
150
+ /site
151
+
152
+ # mypy
153
+ .mypy_cache/
154
+ .dmypy.json
155
+ dmypy.json
156
+
157
+ # Pyre type checker
158
+ .pyre/
159
+
160
+ # pytype static type analyzer
161
+ .pytype/
162
+
163
+ # Cython debug symbols
164
+ cython_debug/
165
+
166
+ # PyCharm
167
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
168
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
169
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
170
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
171
+ #.idea/
172
+
173
+ # Ruff stuff:
174
+ .ruff_cache/
175
+
176
+ # PyPI configuration file
177
+ .pypirc
data/descriptions.csv ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ id,description,category
2
+ 0,a purple forest at dusk,landscape
3
+ 1,gray wool coat with a faux fur collar,fashion
4
+ 2,a lighthouse overlooking the ocean,landscape
5
+ 3,burgundy corduroy pants with patch pockets and silver buttons,fashion
6
+ 4,orange corduroy overalls,fashion
7
+ 5,a purple silk scarf with tassel trim,fashion
8
+ 6,a green lagoon under a cloudy sky,landscape
9
+ 7,crimson rectangles forming a chaotic grid,abstract
10
+ 8,purple pyramids spiraling around a bronze cone,abstract
11
+ 9,magenta trapezoids layered on a transluscent silver sheet,abstract
12
+ 10,a snowy plain,landscape
13
+ 11,black and white checkered pants,fashion
14
+ 12,a starlit night over snow-covered peaks,landscape
15
+ 13,khaki triangles and azure crescents,abstract
16
+ 14,a maroon dodecahedron interwoven with teal threads,abstract
17
+ 14,a peaceful meadow under a bright blue sky,landscapes
18
+ 15,a bright coral beach at midday,landscapes
19
+ 16,a misty morning over a tranquil fjord,landscapes
20
+ 17,an arctic tundra blanketed in snow,landscapes
21
+ 18,rolling hills covered in wildflowers,landscapes
22
+ 19,a peaceful hillside dotted with grazing animals,landscapes
23
+ 20,a tranquil lake surrounded by mountains,landscapes
24
+ 21,a rocky outcrop with panoramic views,landscapes
25
+ 22,a tranquil beach with soft white sands,landscapes
26
+ 23,a hidden waterfall cascading into a serene pool,landscapes
27
+ 24,a serene bay with anchored sailboats,landscapes
28
+ 25,a peaceful orchard in full bloom,landscapes
29
+ 26,a shimmering ice field reflecting the sun,landscapes
30
+ 27,a calm river reflecting the changing leaves,landscapes
31
+ 28,a vibrant autumn forest ablaze with colors,landscapes
32
+ 29,a tranquil forest path lined with ferns,landscapes
33
+ 30,a lush jungle vibrant with life,landscapes
34
+ 31,a sunlit plateau with sprawling grasslands,landscapes
35
+ 32,a quiet pond with lily pads and frogs,landscapes
36
+ 33,an endless field of sunflowers reaching for the sky,landscapes
37
+ 34,a craggy shoreline kissed by foamy waves,landscapes
38
+ 35,a vibrant city skyline at twilight,landscapes
39
+ 36,a grassy hilltop with sweeping views,landscapes
40
+ 37,"a narrow canyon with steep, colorful walls",landscapes
41
+ 38,a secluded glen with singing streams,landscapes
42
+ 39,a winding path through golden autumn leaves,landscapes
43
+ 40,a deserted island surrounded by turquoise waters,landscapes
44
+ 41,a rocky plateau under a blanket of stars,landscapes
45
+ 42,a golden desert at sunset,landscapes
46
+ 43,a sunlit glade filled with chirping birds,landscapes
47
+ 44,a vibrant coral reef beneath crystal waters,landscapes
48
+ 45,a striking basalt cliff alongside a river,landscapes
49
+ 46,a verdant valley framed by majestic peaks,landscapes
50
+ 47,a remote mountain lake surrounded by pines,landscapes
51
+ 48,a quaint village nestled in rolling hills,landscapes
52
+ 49,an ancient forest bathed in moonlight,landscapes
53
+ 50,a colorful wildflower meadow in full bloom,landscapes
54
+ 51,a sun-drenched vineyard on a gentle slope,landscapes
55
+ 52,a lush garden bursting with colors,landscapes
56
+ 53,a windswept dune under a vast sky,landscapes
57
+ 54,a misty valley at dawn,landscapes
58
+ 55,a rocky cliff overlooking a shimmering sea,landscapes
59
+ 56,a rugged coastline with crashing waves,landscapes
60
+ 57,a colorful canyon painted by nature’s brush,landscapes
61
+ 58,a misty mountain range shrouded in clouds,landscapes
62
+ 59,an expansive savanna dotted with acacia trees,landscapes
63
+ 60,a secluded cove with clear blue waters,landscapes
64
+ 61,a foggy marsh with tall grasses swaying,landscapes
65
+ 62,a serene river winding through lush greenery,landscapes
66
+ 63,a dramatic volcanic landscape with black sands,landscapes
67
+ 64,a dance of teal waves and coral stripes in motion,abstract
68
+ 65,intermingled shades of peach and plum creating warmth,abstract
69
+ 66,a burst of burnt orange triangles against pale blue,abstract
70
+ 67,bright cyan squares floating in a sea of dark gray,abstract
71
+ 68,a chaotic arrangement of yellow and purple lines,abstract
72
+ 69,"bold, vibrant colors colliding in rhythmic patterns",abstract
73
+ 70,sapphire spirals intertwining with silver rectangles,abstract
74
+ 71,layers of olive and gold squares forming depth,abstract
75
+ 72,crimson and cobalt circles spiraling inward,abstract
76
+ 73,layered translucent shapes in shades of teal and jade,abstract
77
+ 74,sharp angles of black and white creating an illusion,abstract
78
+ 75,a cascade of fuchsia polygons on a cream backdrop,abstract
79
+ 76,golden circles overlapping with deep blue squares,abstract
80
+ 77,yellow triangles punctuated by black dots on white,abstract
81
+ 78,geometric clouds of gray juxtaposed with fiery reds,abstract
82
+ 79,a patchwork of deep reds and bright yellows,abstract
83
+ 80,a mosaic of lavender hexagons on a charcoal background,abstract
84
+ 81,woven threads of silver and burgundy forming landscapes,abstract
85
+ 82,turquoise lines radiating from a central ruby star,abstract
86
+ 83,a lattice of mauve and chartreuse intersecting forms,abstract
87
+ 84,chaotic lines of dark green tracing a golden background,abstract
88
+ 85,emerald diamonds scattered across a warm orange canvas,abstract
89
+ 86,diagonal lines of plum and mint creating tension,abstract
90
+ 87,bold black squares anchored by splashes of turquoise,abstract
91
+ 88,a whirl of soft lavender and sharp black angles,abstract
92
+ 89,soft pink spirals weaving through a canvas of cream,abstract
93
+ 90,a balanced composition of red circles and blue lines,abstract
94
+ 91,pulsating layers of orange and purple creating depth,abstract
95
+ 92,whispering curves of lavender on a deep black canvas,abstract
96
+ 93,a field of intersecting lines in soft earth tones,abstract
97
+ 94,a cluster of copper diamonds floating on deep azure,abstract
98
+ 95,a dynamic interplay of orange and teal shapes,abstract
99
+ 96,gentle curves of olive green and burnt sienna,abstract
100
+ 97,a field of gray circles encircled by vibrant yellows,abstract
101
+ 98,violet waves flowing through a grid of muted greens,abstract
102
+ 99,textured green rectangles layered over a soft beige,abstract
103
+ 100,intersecting teal and amber shapes on a stark white,abstract
104
+ 101,a swirl of pastel circles against a dark indigo field,abstract
105
+ 102,a burst of bright colors scattered across gentle curves,abstract
106
+ 103,jagged navy triangles contrasting against a light canvas,abstract
107
+ 104,golden rays emerging from a central violet orb,abstract
108
+ 105,cyan and magenta triangles creating visual tension,abstract
109
+ 106,pastel arcs dancing across a canvas of dark navy,abstract
110
+ 107,layered rectangles in shades of rose and steel gray,abstract
111
+ 108,a rhythmic pattern of orange and white stripes,abstract
112
+ 109,fractured shapes of green and gold evoking movement,abstract
113
+ 110,interlocking beige ovals on a vibrant cerulean base,abstract
114
+ 111,abstract black and white circles creating visual harmony,abstract
115
+ 112,crimson arcs and navy triangles creating dynamic tension,abstract
116
+ 113,overlapping shapes in muted tones of green and brown,abstract
117
+ 114,two-tone canvas slip-ons in navy and white,fashion
118
+ 115,soft ankle socks in pastel colors with a ribbed top,fashion
119
+ 116,luxe velvet dress in deep emerald with a wrap design,fashion
120
+ 117,soft merino wool pullover in muted lavender,fashion
121
+ 118,high-waisted shorts in a lightweight chambray fabric,fashion
122
+ 119,classic trench coat in beige with a tie belt,fashion
123
+ 120,soft fleece hoodie in light gray with a kangaroo pocket,fashion
124
+ 121,graphic tee in soft cotton with a vintage design,fashion
125
+ 122,satin camisole in blush pink with delicate lace trim,fashion
126
+ 123,plaid wool skirt with a high waist and pleats,fashion
127
+ 124,chevron knit blanket scarf in shades of gray,fashion
128
+ 125,classic white button-up shirt with a tailored fit,fashion
129
+ 126,cotton twill chinos in olive green with a slim fit,fashion
130
+ 127,floral print wrap dress with flutter sleeves,fashion
131
+ 128,denim overalls with a relaxed fit and side buttons,fashion
132
+ 129,chunky heeled sandals in tan leather with ankle strap,fashion
133
+ 130,sleek pencil skirt in faux leather with a back slit,fashion
134
+ 131,fitted turtleneck in soft cotton in rich burgundy,fashion
135
+ 132,knitted cardigan in soft beige with patch pockets,fashion
136
+ 133,sleek black leather ankle boots with a pointed toe,fashion
137
+ 134,canvas sneakers in bright yellow with white soles,fashion
138
+ 135,elegant silk blouse featuring ruffled cuffs,fashion
139
+ 136,cropped bomber jacket in olive green with ribbed cuffs,fashion
140
+ 137,vibrant floral maxi dress with a cinched waist,fashion
141
+ 138,soft flannel shirt in checkered red and black,fashion
142
+ 139,chunky knit scarf in cream with fringed edges,fashion
143
+ 140,tailored trousers in classic black with a straight cut,fashion
144
+ 141,lightweight denim jacket with frayed hem and pockets,fashion
145
+ 142,leather crossbody bag with an adjustable strap,fashion
146
+ 143,striped linen shirt with rolled-up sleeves,fashion
147
+ 144,flowy midi skirt with a watercolor print,fashion
148
+ 145,soft jersey t-shirt in pastel pink with a crew neck,fashion
149
+ 146,ribbed knit beanie in charcoal gray,fashion
150
+ 147,soft cashmere sweater in a rich navy blue,fashion
151
+ 148,vintage-inspired high-waisted jeans in dark wash,fashion
152
+ 149,cotton sundress in bright yellow with a flared skirt,fashion
153
+ 150,distressed denim jacket with a faded finish,fashion
154
+ 151,lightweight parka in navy with a hood and drawstrings,fashion
155
+ 152,pleated satin trousers in metallic gold,fashion
156
+ 153,distressed boyfriend jeans with a relaxed silhouette,fashion
157
+ 154,wool beanie in forest green with a cuffed edge,fashion
158
+ 155,mesh-paneled leggings for active wear,fashion
159
+ 156,canvas tote bag with a bold graphic print,fashion
160
+ 157,long-sleeve wrap top in crisp white with a tie detail,fashion
161
+ 158,midi dress in a bold animal print with a flowy hem,fashion
162
+ 159,tailored shorts in crisp white with a hidden zipper,fashion
163
+ 160,fitted blazer in a rich burgundy hue,fashion
164
+ 161,quilted puffer vest in bright red with zip pockets,fashion
165
+ 162,polka dot silk scarf in navy with white spots,fashion
166
+ 163,sheer kimono in floral chiffon with wide sleeves,fashion
data/eval.csv ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ id,question,choices,answer
2
+ 0,"[""What color are the trees in the forest?"", ""What time of day is depicted in the image?"", ""Are there any visible animals in the forest?"", ""What is the sky's color like in the image?"", ""Is there a path or trail visible in the forest?""]","[[""green"", ""purple"", ""brown"", ""yellow""], [""morning"", ""afternoon"", ""dusk"", ""midnight""], [""yes"", ""no""], [""blue"", ""purple"", ""orange"", ""gray""], [""yes"", ""no""]]","[""purple"", ""dusk"", ""no"", ""purple"", ""no""]"
3
+ 1,"[""What color is the coat?"", ""What type of collar does the coat have?"", ""Is the coat long-sleeved or short-sleeved?"", ""What material is the coat made of?""]","[[""gray"", ""black"", ""brown"", ""blue""], [""faux fur"", ""cotton"", ""leather"", ""silk""], [""long-sleeved"", ""short-sleeved"", ""sleeveless""], [""wool"", ""denim"", ""polyester"", ""nylon""]]","[""gray"", ""faux fur"", ""long-sleeved"", ""wool""]"
4
+ 2,"[""What color is the lighthouse?"", ""Are there any waves in the ocean?"", ""Is there a sun or moon in the sky?"", ""What is the primary color of the ocean?"", ""Does the lighthouse have a light at the top?""]","[[""red"", ""blue"", ""green"", ""white""], [""yes"", ""no""], [""sun"", ""moon"", ""none""], [""blue"", ""green"", ""brown"", ""gray""], [""yes"", ""no""]]","[""red"", ""yes"", ""sun"", ""blue"", ""yes""]"
5
+ 3,"[""What color are the pants?"", ""What type of fabric are the pants made of?"", ""How many pockets do the pants have?"", ""What color are the buttons on the pants?""]","[[""red"", ""burgundy"", ""blue"", ""black""], [""denim"", ""corduroy"", ""cotton"", ""wool""], [""1"", ""2"", ""3"", ""4""], [""gold"", ""silver"", ""black"", ""white""]]","[""burgundy"", ""corduroy"", ""2"", ""silver""]"
6
+ 4,"[""What color are the overalls?"", ""What texture is depicted on the overalls?"", ""Are there any straps visible on the overalls?"", ""What type of clothing is represented in the image?""]","[[""blue"", ""orange"", ""green"", ""red""], [""smooth"", ""corduroy"", ""denim"", ""silk""], [""yes"", ""no""], [""shirt"", ""pants"", ""overalls"", ""jacket""]]","[""orange"", ""corduroy"", ""yes"", ""overalls""]"
7
+ 5,"[""What is the main color of the scarf?"", ""Does the scarf have any decorative trim?"", ""What material is the scarf made of?"", ""What kind of embellishments are present on the scarf?"", ""Is the scarf depicted as being tied or loose?""]","[[""red"", ""purple"", ""blue"", ""green""], [""yes"", ""no""], [""cotton"", ""silk"", ""wool"", ""linen""], [""beads"", ""tassels"", ""fringe"", ""embroidery""], [""tied"", ""loose""]]","[""purple"", ""yes"", ""silk"", ""tassels"", ""loose""]"
8
+ 6,"[""What color is the lagoon?"", ""Are there clouds in the sky?"", ""What is the predominant color of the sky?"", ""Is there any land visible around the lagoon?""]","[[""blue"", ""green"", ""yellow"", ""red""], [""yes"", ""no""], [""gray"", ""blue"", ""white"", ""black""], [""yes"", ""no""]]","[""green"", ""yes"", ""gray"", ""no""]"
9
+ 7,"[""What color are the rectangles in the image?"", ""Are the rectangles arranged in a uniform grid?"", ""What is the overall visual theme of the rectangles?"", ""Do the rectangles vary in size?""]","[[""blue"", ""crimson"", ""green"", ""yellow""], [""yes"", ""no""], [""chaotic"", ""structured"", ""minimalist"", ""symmetrical""], [""yes"", ""no""]]","[""crimson"", ""no"", ""chaotic"", ""yes""]"
10
+ 8,"[""What color are the pyramids in the image?"", ""What is the shape of the main element at the center?"", ""How are the pyramids arranged around the cone?"", ""What material does the cone appear to be?""]","[[""red"", ""purple"", ""blue"", ""green""], [""sphere"", ""cube"", ""cone"", ""pyramid""], [""spiraling"", ""stacked"", ""scattered"", ""aligned""], [""gold"", ""silver"", ""bronze"", ""copper""]]","[""purple"", ""cone"", ""spiraling"", ""bronze""]"
11
+ 9,"[""What color are the trapezoids?"", ""What is the texture of the sheet behind the trapezoids?"", ""How many trapezoids are layered on the sheet?"", ""What can be inferred about the visibility of the trapezoids?"", ""What geometric shape is featured in the image?""]","[[""red"", ""magenta"", ""blue"", ""green""], [""opaque"", ""glossy"", ""translucent"", ""matte""], [""one"", ""two"", ""three"", ""multiple""], [""they are fully visible"", ""they are partially hidden"", ""they are not visible""], [""circle"", ""square"", ""trapezoid"", ""triangle""]]","[""magenta"", ""translucent"", ""multiple"", ""they are partially hidden"", ""trapezoid""]"
12
+ 10,"[""What is the predominant color of the plain?"", ""Are there any trees visible in the image?"", ""What type of weather is depicted in the image?"", ""Is there a sun or moon in the sky?""]","[[""white"", ""green"", ""brown"", ""blue""], [""yes"", ""no""], [""snowy"", ""sunny"", ""rainy"", ""cloudy""], [""sun"", ""moon"", ""none"", ""both""]]","[""white"", ""no"", ""snowy"", ""none""]"
13
+ 11,"[""What color are the pants?"", ""What pattern is visible on the pants?"", ""Are the pants striped or checkered?"", ""Is there any color other than black and white in the pants?""]","[[""black"", ""white"", ""gray"", ""red""], [""solid"", ""polka dot"", ""checkered"", ""floral""], [""striped"", ""checkered"", ""plaid"", ""solid""], [""yes"", ""no""]]","[""black"", ""checkered"", ""checkered"", ""no""]"
14
+ 12,"[""What kind of peaks are depicted in the image?"", ""What is the color of the sky in the image?"", ""Are there any stars visible in the image?"", ""What season does the image represent?""]","[[""rocky"", ""snow-covered"", ""forest-covered"", ""flat""], [""blue"", ""black"", ""gray"", ""orange""], [""yes"", ""no""], [""spring"", ""summer"", ""autumn"", ""winter""]]","[""snow-covered"", ""black"", ""yes"", ""winter""]"
15
+ 13,"[""What color are the triangles?"", ""What shape do the azure elements resemble?"", ""How many different colors are used in the image?"", ""Which color is associated with the triangles?"", ""Are the crescents depicted in a solid color?""]","[[""green"", ""khaki"", ""blue"", ""red""], [""squares"", ""crescents"", ""rectangles"", ""triangles""], [""one"", ""two"", ""three"", ""four""], [""khaki"", ""azure"", ""yellow"", ""purple""], [""yes"", ""no"", ""partially"", ""unknown""]]","[""khaki"", ""crescents"", ""two"", ""khaki"", ""no""]"
16
+ 14,"[""What color is the dodecahedron?"", ""What color are the threads interwoven with the dodecahedron?"", ""How many faces does the dodecahedron have?"", ""What is the primary geometric shape depicted in the image?""]","[[""red"", ""maroon"", ""blue"", ""green""], [""teal"", ""yellow"", ""pink"", ""black""], [""6"", ""12"", ""20"", ""8""], [""cube"", ""tetrahedron"", ""dodecahedron"", ""octahedron""]]","[""maroon"", ""teal"", ""12"", ""dodecahedron""]"
17
+ 14,"[""What color is the sky in the image?"", ""What type of vegetation is predominant in the meadow?"", ""Are there any clouds in the sky?"", ""Is there any water present in the meadow?"", ""What is the overall mood conveyed by the image?""]","[[""blue"", ""gray"", ""white"", ""green""], [""grass"", ""desert"", ""trees"", ""flowers""], [""yes"", ""no""], [""yes"", ""no""], [""peaceful"", ""chaotic"", ""gloomy"", ""dark""]]","[""blue"", ""grass"", ""no"", ""no"", ""peaceful""]"
18
+ 15,"[""What color is the beach in the image?"", ""What time of day is depicted in the image?"", ""Are there any palm trees on the beach?"", ""What is the condition of the sky in the image?""]","[[""bright coral"", ""dark brown"", ""sand yellow"", ""deep blue""], [""morning"", ""midday"", ""evening"", ""night""], [""yes"", ""no""], [""clear"", ""cloudy"", ""stormy"", ""sunset""]]","[""bright coral"", ""midday"", ""yes"", ""clear""]"
19
+ 16,"[""What is the predominant weather condition depicted in the image?"", ""What color is the water of the fjord?"", ""Are there any mountains or cliffs visible in the background?"", ""Is there any visible wildlife in the image?"", ""What type of sky is depicted in the image?""]","[[""clear"", ""misty"", ""rainy"", ""snowy""], [""blue"", ""gray"", ""green"", ""brown""], [""yes"", ""no""], [""yes"", ""no""], [""sunny"", ""cloudy"", ""misty"", ""stormy""]]","[""misty"", ""gray"", ""yes"", ""no"", ""misty""]"
20
+ 17,"[""What is the predominant color of the landscape?"", ""Are there any trees visible in the image?"", ""What type of animal might be present in the tundra?"", ""Is the sky clear or cloudy?""]","[[""blue"", ""green"", ""white"", ""brown""], [""yes"", ""no""], [""penguin"", ""caribou"", ""lion"", ""elephant""], [""clear"", ""cloudy"", ""sunset"", ""stormy""]]","[""white"", ""no"", ""caribou"", ""cloudy""]"
21
+ 18,"[""What color are the wildflowers?"", ""Are the hills smooth or rugged?"", ""What is the overall mood of the landscape?"", ""Is there a body of water visible in the image?"", ""What season does the landscape depict?""]","[[""red"", ""yellow"", ""blue"", ""mixed""], [""smooth"", ""rugged""], [""serene"", ""stormy"", ""chaotic"", ""desolate""], [""yes"", ""no""], [""spring"", ""summer"", ""autumn"", ""winter""]]","[""mixed"", ""smooth"", ""serene"", ""no"", ""spring""]"
22
+ 19,"[""What type of landscape is depicted in the image?"", ""What color are the grazing animals primarily?"", ""Are there any trees on the hillside?"", ""Is there a body of water visible in the image?"", ""What is the overall mood conveyed by the image?""]","[[""mountainous"", ""hillside"", ""flatland"", ""desert""], [""black"", ""brown"", ""white"", ""multicolored""], [""yes"", ""no""], [""yes"", ""no""], [""peaceful"", ""chaotic"", ""somber"", ""dynamic""]]","[""hillside"", ""brown"", ""yes"", ""no"", ""peaceful""]"
23
+ 20,"[""What color is the water in the lake?"", ""What type of terrain is surrounding the lake?"", ""Are there any trees visible near the lake?""]","[[""blue"", ""green"", ""brown"", ""red""], [""mountains"", ""plains"", ""desert"", ""hills""], [""yes"", ""no""]]","[""blue"", ""mountains"", ""no""]"
24
+ 21,"[""What type of terrain is depicted in the image?"", ""Are there any trees visible in the image?"", ""Does the image show any bodies of water?"", ""What is the predominant color of the rocky outcrop?"", ""Can you see a horizon line in the image?""]","[[""flat"", ""rocky"", ""sandy"", ""mountainous""], [""yes"", ""no""], [""yes"", ""no""], [""gray"", ""green"", ""blue"", ""brown""], [""yes"", ""no""]]","[""rocky"", ""no"", ""no"", ""gray"", ""yes""]"
25
+ 22,"[""What color is the sand on the beach?"", ""Are there any palm trees in the image?"", ""What is the texture of the sand depicted in the image?"", ""Is there water visible in the image?"", ""Are there any people on the beach?""]","[[""white"", ""yellow"", ""black"", ""gray""], [""yes"", ""no""], [""rough"", ""soft"", ""rocky"", ""sandy""], [""yes"", ""no""], [""yes"", ""no""]]","[""white"", ""no"", ""soft"", ""yes"", ""no""]"
26
+ 23,"[""What is the primary feature of the image?"", ""What color is the water in the pool?"", ""Is the waterfall visible in the image?"", ""What kind of atmosphere does the pool convey?""]","[[""waterfall"", ""mountain"", ""forest"", ""sky""], [""blue"", ""green"", ""clear"", ""brown""], [""yes"", ""no""], [""serene"", ""chaotic"", ""dark"", ""bright""]]","[""waterfall"", ""clear"", ""no"", ""serene""]"
27
+ 24,"[""How many sailboats are anchored in the bay?"", ""What color are the sailboats?"", ""Is there a visible shoreline in the image?"", ""What is the overall mood conveyed by the image?"", ""Are there any clouds in the sky?""]","[[""1-2"", ""3-4"", ""5-6"", ""More than 6""], [""Red"", ""Blue"", ""White"", ""Green""], [""Yes"", ""No""], [""Serene"", ""Chaotic"", ""Sad"", ""Dramatic""], [""Yes"", ""No""]]","[""3-4"", ""White"", ""Yes"", ""Serene"", ""Yes""]"
28
+ 25,"[""What color are the blossoms in the orchard?"", ""Are there any trees in the orchard?"", ""Is there a path visible in the orchard?"", ""What type of landscape is depicted in the image?""]","[[""pink"", ""blue"", ""yellow"", ""green""], [""yes"", ""no""], [""yes"", ""no""], [""mountainous"", ""urban"", ""rural"", ""desert""]]","[""pink"", ""yes"", ""yes"", ""rural""]"
29
+ 26,"[""What color predominates the ice field?"", ""What feature is likely seen in the sky?"", ""What effect is visible on the surface of the ice?"", ""What time of day does the scene suggest?""]","[[""blue"", ""green"", ""brown"", ""gray""], [""clouds"", ""stars"", ""sun"", ""moon""], [""shimmering"", ""matte"", ""dull"", ""rough""], [""morning"", ""noon"", ""evening"", ""night""]]","[""blue"", ""sun"", ""shimmering"", ""noon""]"
30
+ 27,"[""What color are the leaves reflecting in the river?"", ""Is the river depicted as calm or turbulent?"", ""What kind of texture might the water surface have?"", ""Are there any animals present in the image?""]","[[""red"", ""blue"", ""green"", ""yellow""], [""calm"", ""turbulent""], [""smooth"", ""rough"", ""bumpy"", ""choppy""], [""yes"", ""no""]]","[""red"", ""calm"", ""smooth"", ""no""]"
31
+ 28,"[""What predominant colors can be seen in the forest?"", ""Are there any animals visible in the image?"", ""What type of trees are primarily depicted in the forest?"", ""Is there a clear sky visible in the image?""]","[[""red, orange, yellow"", ""blue, green, purple"", ""black, white, gray""], [""yes"", ""no""], [""evergreen"", ""deciduous"", ""cacti"", ""palm""], [""yes"", ""no""]]","[""red, orange, yellow"", ""no"", ""deciduous"", ""no""]"
32
+ 29,"[""What type of vegetation lines the path?"", ""Is the path straight or winding?"", ""What is the overall mood of the image?"", ""Are there any animals visible in the image?""]","[[""flowers"", ""ferns"", ""trees"", ""grass""], [""straight"", ""winding""], [""tranquil"", ""chaotic"", ""gloomy"", ""bright""], [""yes"", ""no""]]","[""ferns"", ""winding"", ""tranquil"", ""no""]"
33
+ 30,"[""What types of plants are predominantly visible in the jungle image?"", ""Are there any animals depicted in the jungle scene?"", ""What color are the leaves in the jungle?"", ""Is there any water element present in the image?"", ""What is the overall mood conveyed by the jungle scene?""]","[[""tropical ferns and palm trees"", ""desert cacti"", ""deciduous trees"", ""coniferous trees""], [""yes, monkeys and birds"", ""no animals"", ""only insects"", ""only reptiles""], [""deep green"", ""brown"", ""yellow"", ""grey""], [""yes, a river"", ""no water"", ""only puddles"", ""a waterfall""], [""tranquil and peaceful"", ""dark and ominous"", ""chaotic and stormy"", ""bright and lively""]]","[""tropical ferns and palm trees"", ""yes, monkeys and birds"", ""deep green"", ""yes, a river"", ""bright and lively""]"
34
+ 31,"[""What is the primary color of the grasslands?"", ""Are there any clouds in the sky?"", ""Is there a river or stream visible in the image?"", ""What time of day does the lighting suggest?"", ""Is there any wildlife depicted in the image?""]","[[""green"", ""brown"", ""yellow"", ""blue""], [""yes"", ""no""], [""yes"", ""no""], [""morning"", ""noon"", ""evening"", ""night""], [""yes"", ""no""]]","[""green"", ""no"", ""no"", ""noon"", ""no""]"
35
+ 32,"[""What color are the lily pads in the pond?"", ""How many frogs are visible in the image?"", ""What is the primary feature of the pond?"", ""Are there any flowers present on the lily pads?""]","[[""green"", ""blue"", ""yellow"", ""red""], [""one"", ""two"", ""three"", ""four""], [""lily pads"", ""fish"", ""turtles"", ""rocks""], [""yes"", ""no""]]","[""green"", ""two"", ""lily pads"", ""no""]"
36
+ 33,"[""What color are the sunflower petals?"", ""Are there any clouds in the sky?"", ""What is the predominant color of the field?"", ""How tall do the sunflowers appear to be?""]","[[""yellow"", ""red"", ""blue"", ""green""], [""yes"", ""no""], [""green"", ""brown"", ""yellow"", ""purple""], [""short"", ""medium"", ""tall"", ""dwarf""]]","[""yellow"", ""no"", ""green"", ""tall""]"
37
+ 34,"[""What type of shoreline is depicted in the image?"", ""Are there visible waves in the image?"", ""What color might the waves be?"", ""What texture is likely seen on the shoreline?"", ""Is there any foliage or vegetation present in the image?""]","[[""sandy"", ""craggy"", ""smooth"", ""rocky""], [""yes"", ""no""], [""blue"", ""green"", ""white"", ""brown""], [""smooth"", ""craggy"", ""flat"", ""sandy""], [""yes"", ""no""]]","[""craggy"", ""yes"", ""white"", ""craggy"", ""no""]"
38
+ 35,"[""What is the predominant color of the sky in the image?"", ""Are there any clouds visible in the skyline?"", ""What type of building is most prominently featured in the skyline?"", ""Is there any light coming from the buildings?"", ""What time of day is depicted in the image?""]","[[""blue"", ""purple"", ""orange"", ""pink""], [""yes"", ""no""], [""skyscrapers"", ""houses"", ""trees"", ""bridges""], [""yes"", ""no""], [""morning"", ""afternoon"", ""twilight"", ""night""]]","[""purple"", ""no"", ""skyscrapers"", ""yes"", ""twilight""]"
39
+ 36,"[""What color primarily represents the grassy hilltop?"", ""Are there any trees visible in the image?"", ""What is the weather condition depicted in the image?"", ""What type of view is visible from the hilltop?""]","[[""green"", ""brown"", ""yellow"", ""blue""], [""yes"", ""no""], [""sunny"", ""cloudy"", ""rainy"", ""snowy""], [""mountains"", ""cityscape"", ""ocean"", ""forest""]]","[""green"", ""yes"", ""sunny"", ""mountains""]"
40
+ 37,"[""What colors are primarily visible on the canyon walls?"", ""How steep are the walls of the canyon?"", ""Is there any vegetation present in the canyon?"", ""What is the width of the canyon?"", ""Does the canyon have a visible sky above it?""]","[[""red and orange"", ""blue and green"", ""grey and brown"", ""black and white""], [""gently sloped"", ""moderately steep"", ""vertical"", ""overhanging""], [""yes"", ""no""], [""very narrow"", ""moderately wide"", ""very wide"", ""not specified""], [""yes"", ""no""]]","[""red and orange"", ""vertical"", ""no"", ""very narrow"", ""yes""]"
41
+ 38,"[""What type of vegetation is primarily depicted in the glen?"", ""Is there a visible stream in the image?"", ""What is the overall color scheme of the image?"", ""Are there any animals present in the glen?"", ""What is the general mood conveyed by the image?""]","[[""tall trees"", ""cacti"", ""desert shrubs"", ""tropical plants""], [""yes"", ""no""], [""bright and vibrant"", ""dark and moody"", ""monochrome"", ""pastel""], [""birds"", ""deer"", ""no animals"", ""fish""], [""peaceful"", ""chaotic"", ""tense"", ""mysterious""]]","[""tall trees"", ""yes"", ""bright and vibrant"", ""birds"", ""peaceful""]"
42
+ 39,"[""What color are the leaves depicted in the image?"", ""What is the primary shape of the path in the image?"", ""Are there any animals visible in the image?"", ""What season is represented by the leaves in the image?"", ""Is the path straight or winding?""]","[[""red"", ""golden"", ""green"", ""brown""], [""straight"", ""winding"", ""zigzag"", ""curved""], [""yes"", ""no"", ""only silhouettes"", ""not sure""], [""spring"", ""summer"", ""autumn"", ""winter""], [""straight"", ""winding"", ""circular"", ""none""]]","[""golden"", ""winding"", ""no"", ""autumn"", ""winding""]"
43
+ 40,"[""What color are the waters surrounding the island?"", ""What type of landform is depicted on the island?"", ""Is there any vegetation visible on the island?"", ""What is the overall atmosphere of the image?""]","[[""blue"", ""turquoise"", ""green"", ""clear""], [""mountain"", ""deserted island"", ""cliff"", ""peninsula""], [""yes"", ""no""], [""crowded"", ""deserted"", ""urban"", ""industrial""]]","[""turquoise"", ""deserted island"", ""yes"", ""deserted""]"
44
+ 41,"[""What type of terrain is depicted in the image?"", ""How is the sky depicted in the image?"", ""Are there any trees visible in the image?"", ""What kind of celestial bodies are present in the sky?""]","[[""sandy beach"", ""rocky plateau"", ""forest"", ""mountain range""], [""clear blue"", ""cloudy"", ""blanket of stars"", ""sunset""], [""yes"", ""no""], [""planets"", ""stars"", ""moons"", ""comets""]]","[""rocky plateau"", ""blanket of stars"", ""no"", ""stars""]"
45
+ 42,"[""What color dominates the sky in the image?"", ""What is the predominant color of the desert sand?"", ""Are there any plants visible in the image?"", ""What time of day is depicted in the image?""]","[[""blue"", ""golden"", ""gray"", ""pink""], [""golden"", ""green"", ""brown"", ""white""], [""yes"", ""no""], [""morning"", ""noon"", ""sunset"", ""midnight""]]","[""golden"", ""golden"", ""no"", ""sunset""]"
46
+ 43,"[""What type of trees are depicted in the glade?"", ""Are there birds visible in the image?"", ""What is the predominant color of the sunlight in the glade?"", ""Is there any water depicted in the scene?""]","[[""oaks"", ""pines"", ""maples"", ""willows""], [""yes"", ""no""], [""yellow"", ""blue"", ""green"", ""red""], [""yes"", ""no""]]","[""oaks"", ""yes"", ""yellow"", ""no""]"
47
+ 44,"[""What color predominates the coral in the image?"", ""What is the clarity of the water above the coral reef?"", ""What type of sea life is likely present in the reef?"", ""What is the general atmosphere of the scene?""]","[[""red"", ""blue"", ""green"", ""yellow""], [""crystal clear"", ""murky"", ""cloudy"", ""dark""], [""fish"", ""crabs"", ""seaweed"", ""all of the above""], [""tranquil"", ""stormy"", ""chaotic"", ""dull""]]","[""red"", ""crystal clear"", ""all of the above"", ""tranquil""]"
48
+ 45,"[""What color dominates the cliff in the image?"", ""Is there a river visible in the image?"", ""What is the texture of the cliff surface?"", ""What is the overall mood conveyed by the image?""]","[[""black"", ""white"", ""blue"", ""green""], [""yes"", ""no""], [""smooth"", ""bumpy"", ""sandy"", ""wet""], [""calm"", ""dramatic"", ""cheerful"", ""sad""]]","[""black"", ""yes"", ""bumpy"", ""dramatic""]"
49
+ 46,"[""What color predominantly represents the valley?"", ""What type of terrain is visible in the foreground?"", ""How are the peaks depicted in relation to the valley?"", ""What is the overall atmosphere of the image?""]","[[""green"", ""brown"", ""blue"", ""yellow""], [""flat"", ""rocky"", ""hilly"", ""sandy""], [""tall and imposing"", ""small and gentle"", ""flat"", ""invisible""], [""stormy"", ""serene"", ""chaotic"", ""urban""]]","[""green"", ""hilly"", ""tall and imposing"", ""serene""]"
50
+ 47,"[""What is the predominant color of the lake?"", ""What type of trees surround the lake?"", ""Is there any visible wildlife near the lake?"", ""What is the terrain around the lake like?"", ""What is the weather condition depicted in the image?""]","[[""blue"", ""green"", ""brown"", ""gray""], [""oak"", ""pines"", ""maple"", ""birch""], [""yes"", ""no""], [""rocky"", ""flat"", ""hilly"", ""sandy""], [""sunny"", ""rainy"", ""foggy"", ""snowy""]]","[""blue"", ""pines"", ""no"", ""rocky"", ""sunny""]"
51
+ 48,"[""What type of landscape is depicted in the image?"", ""Are there any houses visible in the village?"", ""What color are the hills in the background?"", ""What type of vegetation is present in the village?""]","[[""mountains"", ""rolling hills"", ""flat plains"", ""desert""], [""yes"", ""no""], [""green"", ""brown"", ""yellow"", ""gray""], [""trees"", ""cacti"", ""palm trees"", ""bushes""]]","[""rolling hills"", ""yes"", ""green"", ""trees""]"
52
+ 49,"[""What is the primary light source in the image?"", ""What type of trees are predominantly depicted in the forest?"", ""Is there any visible wildlife in the image?"", ""What is the overall color tone of the forest scene?""]","[[""moonlight"", ""sunlight"", ""firelight"", ""torchlight""], [""pines"", ""oaks"", ""willows"", ""maples""], [""yes"", ""no""], [""warm hues"", ""cool hues"", ""black and white"", ""bright colors""]]","[""moonlight"", ""pines"", ""no"", ""cool hues""]"
53
+ 50,"[""What colors are predominantly visible in the wildflower meadow?"", ""Are there any trees in the background of the meadow?"", ""What type of flowers can be seen in the meadow?"", ""Is there a clear blue sky above the meadow?"", ""What is the overall mood conveyed by the image?""]","[[""red, yellow, blue, green"", ""black and white"", ""monochrome"", ""pastel colors""], [""yes"", ""no""], [""roses"", ""daisies"", ""sunflowers"", ""all of the above""], [""yes"", ""no""], [""cheerful"", ""gloomy"", ""neutral"", ""tense""]]","[""red, yellow, blue, green"", ""no"", ""all of the above"", ""yes"", ""cheerful""]"
54
+ 51,"[""What type of landscape is depicted in the image?"", ""Are there rows of plants visible in the vineyard?"", ""What is the predominant weather condition suggested by the description?"", ""Is there a sun present in the image?"", ""What color might the grapes in the vineyard be?""]","[[""mountainous"", ""flat"", ""gentle slope"", ""hilly""], [""yes"", ""no""], [""rainy"", ""sunny"", ""stormy"", ""foggy""], [""yes"", ""no""], [""green"", ""red"", ""purple"", ""all of the above""]]","[""gentle slope"", ""yes"", ""sunny"", ""yes"", ""all of the above""]"
55
+ 52,"[""What type of flowers are prominently featured in the garden?"", ""Are there any trees visible in the garden?"", ""What color dominates the flowers in the garden?"", ""Is there any visible pathway in the garden?"", ""What type of foliage can be observed in the garden?""]","[[""roses"", ""daisies"", ""tulips"", ""sunflowers""], [""yes"", ""no""], [""yellow"", ""blue"", ""pink"", ""white""], [""yes"", ""no""], [""ferns"", ""cacti"", ""pines"", ""bamboo""]]","[""tulips"", ""yes"", ""pink"", ""yes"", ""ferns""]"
56
+ 53,"[""What is the primary feature of the landscape?"", ""How does the sky appear in the image?"", ""What texture is likely present on the dune?"", ""What colors might dominate the scene?""]","[[""a windswept dune"", ""a forest"", ""a mountain"", ""a lake""], [""clear and blue"", ""stormy and dark"", ""sunset hues"", ""cloudy""], [""smooth and soft"", ""rocky and rough"", ""wet and muddy"", ""frozen and hard""], [""sandy beige and yellow"", ""green and brown"", ""blue and grey"", ""purple and pink""]]","[""a windswept dune"", ""clear and blue"", ""smooth and soft"", ""sandy beige and yellow""]"
57
+ 54,"[""What color dominates the sky in the image?"", ""Are there any trees visible in the valley?"", ""What is the predominant weather condition depicted?"", ""Is there a river or stream in the valley?"", ""What time of day is represented in the image?""]","[[""blue"", ""orange"", ""gray"", ""purple""], [""yes"", ""no""], [""clear"", ""foggy"", ""rainy"", ""snowy""], [""yes"", ""no""], [""dawn"", ""noon"", ""dusk"", ""midnight""]]","[""orange"", ""yes"", ""foggy"", ""no"", ""dawn""]"
58
+ 55,"[""What color is the sea in the image?"", ""What type of terrain is depicted in the image?"", ""Are there any clouds in the sky?"", ""What is the texture of the cliff?"", ""Is there any vegetation on the cliff?""]","[[""blue"", ""green"", ""gray"", ""brown""], [""rocky"", ""sandy"", ""flat"", ""hilly""], [""yes"", ""no""], [""smooth"", ""rough"", ""wet"", ""dry""], [""yes"", ""no""]]","[""blue"", ""rocky"", ""no"", ""rough"", ""no""]"
59
+ 56,"[""What type of terrain is depicted in the image?"", ""Are there any visible waves in the image?"", ""What colors are predominantly used to represent the sea?"", ""Is there any vegetation shown along the coastline?""]","[[""sandy beach"", ""rugged coastline"", ""flat plain"", ""mountainous region""], [""yes"", ""no""], [""blue and white"", ""green and yellow"", ""brown and gray"", ""red and orange""], [""yes"", ""no""]]","[""rugged coastline"", ""yes"", ""blue and white"", ""no""]"
60
+ 57,"[""What colors dominate the canyon's landscape?"", ""Are there any water features visible in the canyon?"", ""What type of vegetation can be seen in the canyon?"", ""Is there a sky visible in the image?"", ""What geological features are prominent in the canyon?""]","[[""red and orange"", ""blue and green"", ""black and white"", ""purple and yellow""], [""yes"", ""no""], [""cacti"", ""pine trees"", ""flowers"", ""none""], [""yes"", ""no""], [""sharp cliffs"", ""flat plains"", ""rolling hills"", ""deep valleys""]]","[""red and orange"", ""no"", ""cacti"", ""yes"", ""sharp cliffs""]"
61
+ 58,"[""What color dominates the mountain range?"", ""Are there visible clouds in the image?"", ""How many peaks are visible in the mountain range?"", ""Is the atmosphere in the image bright and clear?""]","[[""green"", ""blue"", ""gray"", ""brown""], [""yes"", ""no""], [""one"", ""two"", ""three"", ""four""], [""yes"", ""no""]]","[""gray"", ""yes"", ""three"", ""no""]"
62
+ 59,"[""What type of trees are prominently featured in the image?"", ""What is the primary color of the grass in the savanna?"", ""How many acacia trees are visible in the image?"", ""Is there a clear sky visible in the image?""]","[[""palm trees"", ""acacia trees"", ""oak trees"", ""birch trees""], [""green"", ""brown"", ""yellow"", ""blue""], [""none"", ""one"", ""several"", ""too many to count""], [""yes"", ""no""]]","[""acacia trees"", ""yellow"", ""several"", ""yes""]"
63
+ 60,"[""What color are the waters in the cove?"", ""Is there any vegetation visible in the image?"", ""What type of landform is surrounding the cove?"", ""Are there any boats in the water?"", ""What is the general atmosphere of the cove?""]","[[""green"", ""blue"", ""brown"", ""clear""], [""yes"", ""no""], [""mountains"", ""flat land"", ""cliffs"", ""sand dunes""], [""yes"", ""no""], [""busy"", ""secluded"", ""industrial"", ""urban""]]","[""blue"", ""yes"", ""cliffs"", ""no"", ""secluded""]"
64
+ 61,"[""What is the predominant atmosphere in the image?"", ""What color are the grasses likely to be?"", ""Is there any visible water in the marsh?"", ""How are the grasses depicted in the image?""]","[[""sunny"", ""foggy"", ""clear"", ""stormy""], [""green"", ""brown"", ""yellow"", ""blue""], [""yes"", ""no""], [""swaying gently"", ""standing still"", ""bent over"", ""dried up""]]","[""foggy"", ""green"", ""yes"", ""swaying gently""]"
65
+ 62,"[""What color is the river in the image?"", ""What type of vegetation surrounds the river?"", ""Is there any wildlife depicted near the river?"", ""What is the overall mood or tone of the image?""]","[[""blue"", ""green"", ""brown"", ""red""], [""tall grass"", ""desert shrubs"", ""lush trees"", ""cacti""], [""birds"", ""fish"", ""deer"", ""none""], [""serene"", ""chaotic"", ""dramatic"", ""gloomy""]]","[""blue"", ""lush trees"", ""none"", ""serene""]"
66
+ 63,"[""What color dominates the sands in the landscape?"", ""What type of geological feature is prominently visible in the image?"", ""Are there any vegetation or plants depicted in the scene?"", ""What is the overall atmosphere of the landscape?""]","[[""black"", ""white"", ""brown"", ""yellow""], [""volcanoes"", ""mountains"", ""rivers"", ""lakes""], [""yes"", ""no""], [""calm"", ""dramatic"", ""peaceful"", ""chaotic""]]","[""black"", ""volcanoes"", ""no"", ""dramatic""]"
67
+ 64,"[""What is the primary color of the waves in the image?"", ""What pattern do the stripes in the image create?"", ""How would you describe the movement of the elements in the image?"", ""Which color is dominant in the stripes?""]","[[""teal"", ""coral"", ""blue"", ""green""], [""horizontal"", ""vertical"", ""diagonal"", ""spiral""], [""static"", ""dynamic"", ""still"", ""fixed""], [""teal"", ""coral"", ""yellow"", ""purple""]]","[""teal"", ""horizontal"", ""dynamic"", ""coral""]"
68
+ 65,"[""What predominant colors are present in the image?"", ""Is there a gradient effect in the image?"", ""What is the overall tone of the image?"", ""Are there any geometric shapes defined in the image?""]","[[""peach and plum"", ""blue and green"", ""red and yellow"", ""black and white""], [""yes"", ""no""], [""warm"", ""cool"", ""neutral"", ""dark""], [""yes"", ""no"", ""only lines"", ""only textures""]]","[""peach and plum"", ""yes"", ""warm"", ""no""]"
69
+ 66,"[""What color are the triangles in the image?"", ""What is the background color of the image?"", ""Are there any circles present in the image?"", ""What shape predominantly features in the image?"", ""How would you describe the arrangement of the triangles?""]","[[""burnt orange"", ""pale blue"", ""green"", ""yellow""], [""burnt orange"", ""pale blue"", ""black"", ""white""], [""yes"", ""no""], [""square"", ""triangle"", ""rectangle"", ""oval""], [""randomly scattered"", ""neatly aligned"", ""overlapping"", ""in a circular pattern""]]","[""burnt orange"", ""pale blue"", ""no"", ""triangle"", ""randomly scattered""]"
70
+ 67,"[""What color are the squares in the image?"", ""What is the background color of the image?"", ""How would you describe the arrangement of the squares?"", ""Are there any circles in the image?"", ""What geometric shape is primarily featured in the image?""]","[[""bright cyan"", ""dark gray"", ""bright red"", ""light blue""], [""dark gray"", ""bright cyan"", ""white"", ""black""], [""floating"", ""stacked"", ""aligned"", ""overlapping""], [""yes"", ""no""], [""square"", ""circle"", ""triangle"", ""rectangle""]]","[""bright cyan"", ""dark gray"", ""floating"", ""no"", ""square""]"
71
+ 68,"[""What colors are predominantly used in the image?"", ""Are the lines predominantly straight, curved, or both?"", ""Is there a pattern to the arrangement of the lines?"", ""Do the lines overlap each other?""]","[[""red and blue"", ""yellow and purple"", ""green and orange""], [""straight"", ""curved"", ""both"", ""neither""], [""yes"", ""no""], [""yes"", ""no""]]","[""yellow and purple"", ""both"", ""no"", ""yes""]"
72
+ 69,"[""Are there contrasting colors present in the image?"", ""What type of patterns can be observed in the image?"", ""Is there a dominant color that stands out in the composition?"", ""Do the shapes in the image appear to be geometric or organic?"", ""Is there a sense of depth created by overlapping colors?""]","[[""yes"", ""no""], [""stripes"", ""polka dots"", ""swirls"", ""rhythmic patterns""], [""yes"", ""no""], [""geometric"", ""organic"", ""both"", ""neither""], [""yes"", ""no""]]","[""yes"", ""rhythmic patterns"", ""yes"", ""both"", ""yes""]"
73
+ 70,"[""What color are the spirals in the image?"", ""What geometric shape is intertwined with the spirals?"", ""What color are the rectangles in the image?"", ""Are the spirals solid or outlined?"", ""How many different shapes are present in the image?""]","[[""blue"", ""green"", ""red"", ""purple""], [""circle"", ""rectangle"", ""triangle"", ""oval""], [""gold"", ""silver"", ""black"", ""white""], [""solid"", ""outlined"", ""dashed"", ""none""], [""one"", ""two"", ""three"", ""four""]]","[""blue"", ""rectangle"", ""silver"", ""solid"", ""two""]"
74
+ 71,"[""What colors are predominantly used in the squares?"", ""Are the squares arranged in a uniform or varying pattern?"", ""What is the overall effect of the layers of squares?"", ""Do the squares overlap to create a sense of depth?"", ""Is there any other shape present in the image?""]","[[""blue and red"", ""olive and gold"", ""black and white"", ""purple and orange""], [""uniform pattern"", ""varying pattern"", ""circular pattern"", ""diagonal pattern""], [""flat appearance"", ""sense of depth"", ""chaotic look"", ""minimalist design""], [""yes"", ""no""], [""yes"", ""no""]]","[""olive and gold"", ""varying pattern"", ""sense of depth"", ""yes"", ""no""]"
75
+ 72,"[""What colors are predominantly used in the circles?"", ""Are the circles arranged in a linear fashion?"", ""Do the circles get larger or smaller as they spiral inward?"", ""How many distinct colors are present in the circles?""]","[[""red and blue"", ""crimson and cobalt"", ""green and yellow"", ""black and white""], [""yes"", ""no""], [""larger"", ""smaller""], [""one"", ""two"", ""three"", ""four""]]","[""crimson and cobalt"", ""no"", ""smaller"", ""two""]"
76
+ 73,"[""What color is predominantly featured in the shapes?"", ""Are the shapes solid or translucent?"", ""How many different shades are present in the image?"", ""What effect do the layered shapes create?"", ""Is there any use of gradients in the image?""]","[[""red"", ""teal"", ""blue"", ""purple""], [""solid"", ""translucent"", ""opaque"", ""transparent""], [""1"", ""2"", ""3"", ""4""], [""depth"", ""flatness"", ""chaos"", ""simplicity""], [""yes"", ""no""]]","[""teal"", ""translucent"", ""2"", ""depth"", ""yes""]"
77
+ 74,"[""What color dominates the sharp angles in the image?"", ""Are there any curved shapes present in the image?"", ""What kind of illusion does the arrangement of black and white create?"", ""How many distinct colors are used in the image?"", ""What geometric shapes are primarily featured in the image?""]","[[""black"", ""white"", ""gray"", ""red""], [""yes"", ""no""], [""depth illusion"", ""motion illusion"", ""color illusion"", ""text illusion""], [""one"", ""two"", ""three"", ""four""], [""triangles"", ""circles"", ""squares"", ""ovals""]]","[""black"", ""no"", ""depth illusion"", ""two"", ""triangles""]"
78
+ 75,"[""What color are the polygons in the image?"", ""What is the background color of the image?"", ""How are the polygons arranged in the image?"", ""What type of shapes are present in the image?""]","[[""red"", ""fuchsia"", ""blue"", ""green""], [""white"", ""cream"", ""pink"", ""yellow""], [""scattered"", ""stacked"", ""in a line"", ""cascading""], [""circles"", ""polygons"", ""lines"", ""squares""]]","[""fuchsia"", ""cream"", ""cascading"", ""polygons""]"
79
+ 76,"[""What color are the circles in the image?"", ""What color are the squares in the image?"", ""Do the circles overlap with the squares?"", ""What is the predominant shape in the image?"", ""Are there any triangles present in the image?""]","[[""gold"", ""blue"", ""red"", ""green""], [""gold"", ""blue"", ""yellow"", ""purple""], [""yes"", ""no""], [""circle"", ""square"", ""triangle"", ""rectangle""], [""yes"", ""no""]]","[""gold"", ""blue"", ""yes"", ""circle"", ""no""]"
80
+ 77,"[""What color are the triangles in the image?"", ""What color are the dots in the image?"", ""What is the background color of the image?"", ""How many distinct colors are present in the image?"", ""What shape is primarily featured in the image?""]","[[""red"", ""yellow"", ""blue"", ""green""], [""black"", ""white"", ""yellow"", ""red""], [""black"", ""gray"", ""white"", ""yellow""], [""two"", ""three"", ""four"", ""five""], [""circle"", ""square"", ""triangle"", ""rectangle""]]","[""yellow"", ""black"", ""white"", ""two"", ""triangle""]"
81
+ 78,"[""What color dominates the clouds in the image?"", ""What type of red is present in the image?"", ""Are the clouds depicted in a geometric style?"", ""Is there a contrast between colors in the image?"", ""What is the overall mood conveyed by the juxtaposition of colors?""]","[[""gray"", ""white"", ""blue"", ""black""], [""fiery red"", ""dark red"", ""pale red"", ""muted red""], [""yes"", ""no""], [""yes"", ""no""], [""calm"", ""chaotic"", ""neutral"", ""sad""]]","[""gray"", ""fiery red"", ""yes"", ""yes"", ""chaotic""]"
82
+ 79,"[""What is the dominant color in the patchwork?"", ""Are there any bright yellow sections in the image?"", ""What type of pattern is depicted in the image?"", ""Is there a mix of deep reds and bright yellows present?""]","[[""deep red"", ""bright yellow"", ""blue"", ""green""], [""yes"", ""no""], [""stripes"", ""polka dots"", ""patchwork"", ""solid""], [""yes"", ""no""]]","[""deep red"", ""yes"", ""patchwork"", ""yes""]"
83
+ 80,"[""What color are the hexagons in the image?"", ""What is the background color of the image?"", ""How many sides does each hexagon have?"", ""Are the hexagons arranged in a regular pattern?"", ""Do the hexagons have a glossy or matte finish?""]","[[""lavender"", ""charcoal"", ""blue"", ""green""], [""charcoal"", ""lavender"", ""white"", ""black""], [""4"", ""5"", ""6"", ""8""], [""yes"", ""no"", ""randomly"", ""diagonally""], [""glossy"", ""matte"", ""transparent"", ""metallic""]]","[""lavender"", ""charcoal"", ""6"", ""yes"", ""matte""]"
84
+ 81,"[""What color predominantly represents the threads in the image?"", ""Are there any natural elements depicted in the landscape?"", ""Do the threads appear to create a sense of depth in the landscape?"", ""What is the secondary color used alongside silver in the weaving?"", ""Is the overall mood of the image warm or cool?""]","[[""silver"", ""gold"", ""blue"", ""green""], [""yes"", ""no""], [""yes"", ""no""], [""burgundy"", ""black"", ""white"", ""yellow""], [""warm"", ""cool""]]","[""silver"", ""yes"", ""yes"", ""burgundy"", ""cool""]"
85
+ 82,"[""What color are the lines radiating from the star?"", ""What shape does the central star resemble?"", ""How many lines are radiating from the central star?"", ""What is the main color of the star in the center?""]","[[""red"", ""turquoise"", ""blue"", ""green""], [""circle"", ""star"", ""square"", ""triangle""], [""2"", ""5"", ""10"", ""8""], [""ruby"", ""sapphire"", ""emerald"", ""diamond""]]","[""turquoise"", ""star"", ""10"", ""ruby""]"
86
+ 83,"[""What primary colors are present in the lattice design?"", ""What type of shapes are primarily used in the image?"", ""How are the mauve and chartreuse forms arranged in relation to each other?"", ""Are the intersecting forms transparent or solid?"", ""Is there a predominant background color in the image?""]","[[""red and blue"", ""mauve and chartreuse"", ""green and yellow"", ""black and white""], [""circles"", ""squares"", ""triangles"", ""irregular forms""], [""overlapping"", ""side by side"", ""stacked"", ""randomly dispersed""], [""transparent"", ""solid"", ""gradient"", ""textured""], [""white"", ""black"", ""none"", ""mauve""]]","[""mauve and chartreuse"", ""irregular forms"", ""overlapping"", ""solid"", ""none""]"
87
+ 84,"[""What is the predominant color of the background?"", ""What color are the chaotic lines?"", ""How would you describe the pattern created by the lines?"", ""Is the background solid or textured?"", ""Are the lines straight or curved?""]","[[""red"", ""blue"", ""gold"", ""green""], [""dark green"", ""light green"", ""brown"", ""black""], [""orderly"", ""chaotic"", ""geometric"", ""symmetrical""], [""solid"", ""textured"", ""patterned"", ""transparent""], [""straight"", ""curved"", ""zigzag"", ""intertwined""]]","[""gold"", ""dark green"", ""chaotic"", ""solid"", ""curved""]"
88
+ 85,"[""What color are the diamonds in the image?"", ""What is the background color of the canvas?"", ""Are the diamonds evenly distributed across the canvas?"", ""Which of the following shapes is present in the image?"", ""What is the overall theme of the image?""]","[[""red"", ""emerald"", ""blue"", ""yellow""], [""green"", ""blue"", ""warm orange"", ""purple""], [""yes"", ""no""], [""circle"", ""square"", ""diamond"", ""triangle""], [""cool colors"", ""warm colors"", ""monochrome"", ""pastel""]]","[""emerald"", ""warm orange"", ""no"", ""diamond"", ""warm colors""]"
89
+ 86,"[""What colors are predominantly used in the image?"", ""What direction do the lines in the image primarily run?"", ""What type of line is featured in the image?""]","[[""red and blue"", ""plum and mint"", ""yellow and green"", ""black and white""], [""horizontal"", ""vertical"", ""diagonal"", ""circular""], [""dashed"", ""solid"", ""curved"", ""zigzag""]]","[""plum and mint"", ""diagonal"", ""solid""]"
90
+ 87,"[""What color are the squares in the image?"", ""What color is used for the splashes in the image?"", ""How many bold black squares are present?"", ""What shape do the splashes take in the image?""]","[[""red"", ""blue"", ""black"", ""green""], [""turquoise"", ""yellow"", ""pink"", ""orange""], [""1"", ""2"", ""3"", ""4""], [""circle"", ""splash"", ""square"", ""triangle""]]","[""black"", ""turquoise"", ""3"", ""splash""]"
91
+ 88,"[""What predominant color is featured in the image?"", ""Are there any curved shapes present in the image?"", ""What type of angles are represented in the image?"", ""Is there a gradient effect in the lavender color?"", ""How does the black elements contrast with the lavender?""]","[[""lavender"", ""red"", ""blue"", ""green""], [""yes"", ""no""], [""sharp"", ""rounded"", ""obtuse"", ""right""], [""yes"", ""no""], [""high contrast"", ""low contrast"", ""no contrast"", ""monochromatic""]]","[""lavender"", ""yes"", ""sharp"", ""yes"", ""high contrast""]"
92
+ 89,"[""What color are the spirals in the image?"", ""What is the background color of the canvas?"", ""Do the spirals have a soft or sharp appearance?"", ""Are the spirals uniform in size or varied?"", ""Is there any other color present besides soft pink and cream?""]","[[""soft pink"", ""bright red"", ""dark blue"", ""yellow""], [""cream"", ""white"", ""light gray"", ""beige""], [""soft"", ""sharp"", ""jagged"", ""angular""], [""uniform"", ""varied"", ""none"", ""overlapping""], [""yes"", ""no""]]","[""soft pink"", ""cream"", ""soft"", ""varied"", ""no""]"
93
+ 90,"[""What color are the circles in the image?"", ""What type of lines are present in the image?"", ""Is there more than one red circle in the composition?"", ""Are the lines in the image curved or straight?""]","[[""red"", ""blue"", ""green"", ""yellow""], [""dotted"", ""solid"", ""wavy"", ""broken""], [""yes"", ""no""], [""curved"", ""straight""]]","[""red"", ""solid"", ""yes"", ""straight""]"
94
+ 91,"[""What colors are primarily used in the image?"", ""Are there visible layers in the design?"", ""Does the image contain any gradients?"", ""Is there a sense of movement in the image?"", ""What is the overall mood conveyed by the colors?""]","[[""red and blue"", ""orange and purple"", ""yellow and green"", ""black and white""], [""yes"", ""no""], [""yes"", ""no""], [""yes"", ""no""], [""calm"", ""energetic"", ""dark"", ""sad""]]","[""orange and purple"", ""yes"", ""yes"", ""yes"", ""energetic""]"
95
+ 92,"[""What color are the curves in the image?"", ""What is the background color of the canvas?"", ""Are the curves sharp or smooth?"", ""Is there any text included in the image?"", ""What vibe do the curves convey?""]","[[""red"", ""blue"", ""lavender"", ""green""], [""white"", ""black"", ""blue"", ""purple""], [""sharp"", ""jagged"", ""smooth"", ""angular""], [""yes"", ""no""], [""aggressive"", ""serene"", ""chaotic"", ""industrial""]]","[""lavender"", ""black"", ""smooth"", ""no"", ""serene""]"
96
+ 93,"[""What color palette is predominantly used in the image?"", ""Are the lines in the image thick or thin?"", ""Is there a geometric shape that stands out prominently?"", ""What is the overall mood conveyed by the color tones?"", ""Are the lines arranged in a random pattern or a structured grid?""]","[[""vibrant colors"", ""soft earth tones"", ""monochrome"", ""bright primary colors""], [""thick"", ""thin"", ""varying thickness"", ""none""], [""circle"", ""square"", ""lines"", ""triangle""], [""calm"", ""chaotic"", ""energetic"", ""sad""], [""random pattern"", ""structured grid"", ""circular pattern"", ""diagonal lines""]]","[""soft earth tones"", ""thin"", ""lines"", ""calm"", ""structured grid""]"
97
+ 94,"[""What color are the diamonds in the image?"", ""What is the background color of the image?"", ""How many diamonds are clustered in the image?"", ""What shape do the diamonds resemble?"", ""Are the diamonds solid or transparent?""]","[[""copper"", ""silver"", ""gold"", ""bronze""], [""deep azure"", ""light blue"", ""green"", ""black""], [""one"", ""three"", ""five"", ""seven""], [""circle"", ""square"", ""diamond"", ""triangle""], [""solid"", ""transparent"", ""striped"", ""dotted""]]","[""copper"", ""deep azure"", ""three"", ""diamond"", ""solid""]"
98
+ 95,"[""What primary color is predominantly featured in the shapes?"", ""Are there any circular shapes present in the image?"", ""Is there a contrast between the colors used in the image?"", ""What geometric shape is predominantly used alongside orange?"", ""Are the shapes overlapping in the image?""]","[[""orange"", ""blue"", ""green"", ""purple""], [""yes"", ""no""], [""yes"", ""no""], [""triangle"", ""rectangle"", ""circle"", ""hexagon""], [""yes"", ""no""]]","[""orange"", ""yes"", ""yes"", ""rectangle"", ""yes""]"
99
+ 96,"[""What colors predominantly appear in the image?"", ""Do the curves in the image appear sharp or gentle?"", ""Is there a dominant color among the olive green and burnt sienna?"", ""Are the curves in the image horizontal, vertical, or flowing?""]","[[""olive green and burnt sienna"", ""blue and yellow"", ""red and white"", ""black and grey""], [""sharp"", ""gentle"", ""jagged"", ""straight""], [""olive green"", ""burnt sienna"", ""both equally"", ""none""], [""horizontal"", ""vertical"", ""flowing"", ""zigzag""]]","[""olive green and burnt sienna"", ""gentle"", ""both equally"", ""flowing""]"
100
+ 97,"[""What color are the circles in the field?"", ""What color encircles the gray circles?"", ""What is the overall shape of the main elements in the image?"", ""Is there a background color in the image?""]","[[""gray"", ""yellow"", ""blue"", ""green""], [""yellow"", ""red"", ""blue"", ""purple""], [""square"", ""circle"", ""triangle"", ""rectangle""], [""yes"", ""no""]]","[""gray"", ""yellow"", ""circle"", ""yes""]"
101
+ 98,"[""What color are the waves in the image?"", ""What is the predominant color of the grid?"", ""How would you describe the overall mood of the image?"", ""Are there any sharp angles in the wave design?"", ""What pattern is the grid made of?""]","[[""blue"", ""violet"", ""green"", ""yellow""], [""bright green"", ""muted green"", ""dark green"", ""neon green""], [""calm and serene"", ""chaotic"", ""dark and gloomy"", ""energetic""], [""yes"", ""no""], [""stripes"", ""dots"", ""squares"", ""random shapes""]]","[""violet"", ""muted green"", ""calm and serene"", ""no"", ""squares""]"
102
+ 99,"[""What is the primary color of the background?"", ""What texture do the rectangles have?"", ""How many green rectangles are layered over the beige background?"", ""What color are the rectangles?"", ""What is the overall tone of the image?""]","[[""green"", ""beige"", ""blue"", ""yellow""], [""smooth"", ""textured"", ""glossy"", ""transparent""], [""one"", ""two"", ""three"", ""multiple""], [""green"", ""red"", ""blue"", ""yellow""], [""vibrant"", ""soft"", ""dark"", ""neon""]]","[""beige"", ""textured"", ""multiple"", ""green"", ""soft""]"
103
+ 100,"[""What color are the intersecting shapes?"", ""What is the background color of the image?"", ""Are the shapes solid or outlined?"", ""How many colors are used in the shapes?"", ""Are the shapes geometric or organic in form?""]","[[""teal and amber"", ""red and blue"", ""green and yellow"", ""purple and orange""], [""white"", ""black"", ""grey"", ""blue""], [""solid"", ""outlined"", ""gradient"", ""transparent""], [""two"", ""three"", ""four"", ""one""], [""geometric"", ""organic"", ""abstract"", ""figurative""]]","[""teal and amber"", ""white"", ""solid"", ""two"", ""geometric""]"
104
+ 101,"[""What color is the background of the image?"", ""Are the circles in the image vibrant or pastel?"", ""What is the overall color scheme of the circles?"", ""Is the background color light or dark?""]","[[""light blue"", ""dark indigo"", ""white"", ""yellow""], [""vibrant"", ""pastel"", ""neon"", ""dark""], [""monochrome"", ""pastel"", ""dark"", ""bright""], [""light"", ""dark""]]","[""dark indigo"", ""pastel"", ""pastel"", ""dark""]"
105
+ 102,"[""What type of colors are predominantly featured in the image?"", ""Are there any straight lines present in the design?"", ""What overall shape do the curves create in the image?"", ""Do the colors appear to be bright or muted?"", ""Is there a gradient effect in the color distribution?""]","[[""bright"", ""muted""], [""yes"", ""no""], [""geometric"", ""organic"", ""abstract""], [""bright"", ""dark""], [""yes"", ""no""]]","[""bright"", ""no"", ""organic"", ""bright"", ""yes""]"
106
+ 103,"[""What color are the triangles in the image?"", ""What background color contrasts with the triangles?"", ""What shape do the prominent elements of the image resemble?"", ""How would you describe the edges of the triangles?""]","[[""red"", ""navy"", ""green"", ""yellow""], [""dark gray"", ""white"", ""light canvas"", ""black""], [""circle"", ""square"", ""triangle"", ""rectangle""], [""smooth"", ""curved"", ""jagged"", ""rounded""]]","[""navy"", ""light canvas"", ""triangle"", ""jagged""]"
107
+ 104,"[""What color is the central orb?"", ""What direction do the rays emerge from?"", ""What color are the rays?"", ""Is the orb larger than the rays?"", ""Are there any other shapes present besides the orb and rays?""]","[[""red"", ""blue"", ""violet"", ""green""], [""upward"", ""downward"", ""outward"", ""inward""], [""gold"", ""silver"", ""black"", ""white""], [""yes"", ""no""], [""yes"", ""no""]]","[""violet"", ""outward"", ""gold"", ""yes"", ""no""]"
108
+ 105,"[""What colors are the triangles in the image?"", ""Are the triangles overlapping?"", ""What is the overall visual effect created by the triangles?"", ""How many distinct colors are used in the triangles?""]","[[""cyan and magenta"", ""red and blue"", ""green and yellow"", ""black and white""], [""yes"", ""no""], [""harmony"", ""visual tension"", ""chaos"", ""balance""], [""one"", ""two"", ""three"", ""four""]]","[""cyan and magenta"", ""yes"", ""visual tension"", ""two""]"
109
+ 106,"[""What color is the background of the image?"", ""What is the general shape of the elements in the image?"", ""Are the arcs primarily in bright, bold colors or softer tones?"", ""How do the arcs appear to be arranged on the canvas?"", ""What is the overall mood conveyed by the color scheme?""]","[[""black"", ""dark navy"", ""light blue"", ""white""], [""lines"", ""squares"", ""arcs"", ""dots""], [""bright and bold"", ""pastel and soft"", ""dark and muted"", ""neutral""], [""randomly scattered"", ""uniformly spaced"", ""layered"", ""overlapping""], [""energetic"", ""somber"", ""playful"", ""neutral""]]","[""dark navy"", ""arcs"", ""pastel and soft"", ""randomly scattered"", ""playful""]"
110
+ 107,"[""What colors are predominantly used in the rectangles?"", ""Are the rectangles layered on top of each other?"", ""What geometric shape is primarily featured in the image?"", ""Is there any gradient effect used in the rectangles?"", ""Are there any circles included in the design?""]","[[""rose and steel gray"", ""blue and yellow"", ""green and black""], [""yes"", ""no""], [""rectangle"", ""circle"", ""triangle"", ""oval""], [""yes"", ""no""], [""yes"", ""no""]]","[""rose and steel gray"", ""yes"", ""rectangle"", ""no"", ""no""]"
111
+ 108,"[""What colors are present in the stripes?"", ""Are the stripes arranged vertically or horizontally?"", ""Is there any other pattern besides stripes in the image?"", ""How many distinct colors are used in the pattern?""]","[[""orange and white"", ""red and white"", ""blue and yellow"", ""green and pink""], [""vertically"", ""horizontally"", ""diagonally"", ""randomly""], [""yes"", ""no""], [""one"", ""two"", ""three"", ""four""]]","[""orange and white"", ""horizontally"", ""no"", ""two""]"
112
+ 109,"[""What colors are predominantly used in the image?"", ""Do the shapes in the image appear to be smooth or fractured?"", ""Is there a sense of movement conveyed by the arrangement of the shapes?"", ""Are the shapes primarily angular or rounded?"", ""What is the overall mood evoked by the colors and shapes?""]","[[""red and blue"", ""green and gold"", ""black and white"", ""purple and orange""], [""smooth"", ""fractured"", ""rounded"", ""flat""], [""yes"", ""no""], [""angular"", ""rounded"", ""circular"", ""elliptical""], [""calm"", ""chaotic"", ""energetic"", ""somber""]]","[""green and gold"", ""fractured"", ""yes"", ""angular"", ""energetic""]"
113
+ 110,"[""What color is the background of the image?"", ""What is the color of the ovals?"", ""How are the ovals arranged in the image?"", ""What shape are the interlocking elements in the image?""]","[[""red"", ""cerulean"", ""beige"", ""green""], [""blue"", ""beige"", ""white"", ""black""], [""stacked"", ""interlocking"", ""scattered"", ""overlapping""], [""squares"", ""triangles"", ""ovals"", ""rectangles""]]","[""cerulean"", ""beige"", ""interlocking"", ""ovals""]"
114
+ 111,"[""What colors are predominantly used in the image?"", ""Are there overlapping circles in the design?"", ""Is there a specific pattern formed by the circles?"", ""What is the overall tone of the image?""]","[[""red and blue"", ""black and white"", ""green and yellow"", ""purple and orange""], [""yes"", ""no""], [""geometric"", ""random"", ""spiral"", ""linear""], [""chaotic"", ""calm"", ""bright"", ""dark""]]","[""black and white"", ""yes"", ""geometric"", ""calm""]"
115
+ 112,"[""What color are the arcs in the image?"", ""What geometric shape is prominently featured in the image?"", ""What color are the triangles in the image?"", ""Do the arcs and triangles create a sense of movement?"", ""Are the arcs and triangles overlapping in the design?""]","[[""crimson"", ""navy"", ""gold"", ""green""], [""circle"", ""triangle"", ""rectangle"", ""oval""], [""crimson"", ""navy"", ""yellow"", ""black""], [""yes"", ""no""], [""yes"", ""no""]]","[""crimson"", ""triangle"", ""navy"", ""yes"", ""yes""]"
116
+ 113,"[""What is the predominant color scheme of the shapes?"", ""Are the shapes primarily geometric or organic?"", ""Do the shapes overlap each other?"", ""What tones are used in the image?"", ""Is there a bright color present in the image?""]","[[""Muted tones of green and brown"", ""Bright colors"", ""Black and white"", ""Vibrant colors""], [""Geometric"", ""Organic"", ""Mixed"", ""Abstract""], [""Yes"", ""No""], [""Warm tones"", ""Cool tones"", ""Muted tones"", ""Neon colors""], [""Yes"", ""No""]]","[""Muted tones of green and brown"", ""Mixed"", ""Yes"", ""Muted tones"", ""No""]"
117
+ 114,"[""What colors are visible on the slip-ons?"", ""Are there any patterns on the canvas slip-ons?"", ""What type of footwear is depicted in the image?"", ""What is the predominant color of the slip-ons?""]","[[""navy and white"", ""red and blue"", ""green and yellow"", ""black and white""], [""yes"", ""no""], [""sandals"", ""boots"", ""slip-ons"", ""loafers""], [""navy"", ""white"", ""gray"", ""black""]]","[""navy and white"", ""no"", ""slip-ons"", ""navy""]"
118
+ 115,"[""What colors are the ankle socks in the image?"", ""What type of top do the socks have?"", ""Are the socks designed for a specific season?"", ""What pattern, if any, is present on the socks?""]","[[""bright colors"", ""pastel colors"", ""dark colors"", ""neon colors""], [""ribbed top"", ""smooth top"", ""frilled top"", ""flat top""], [""summer"", ""winter"", ""year-round"", ""fall""], [""striped"", ""polka dots"", ""solid color"", ""floral""]]","[""pastel colors"", ""ribbed top"", ""year-round"", ""solid color""]"
119
+ 116,"[""What color is the dress?"", ""What type of fabric is the dress made of?"", ""What design feature does the dress have?"", ""Is the dress long or short?"", ""Does the dress have sleeves?""]","[[""red"", ""deep emerald"", ""blue"", ""black""], [""cotton"", ""silk"", ""velvet"", ""denim""], [""wrap design"", ""A-line"", ""fit and flare"", ""ball gown""], [""long"", ""short"", ""knee-length"", ""mid-calf""], [""yes"", ""no""]]","[""deep emerald"", ""velvet"", ""wrap design"", ""long"", ""no""]"
120
+ 117,"[""What color is the pullover?"", ""What material is the pullover made of?"", ""What style of clothing does the image depict?"", ""Is the pullover textured or smooth?"", ""What is the overall tone of the pullover's color?""]","[[""red"", ""muted lavender"", ""blue"", ""green""], [""cotton"", ""silk"", ""merino wool"", ""polyester""], [""jacket"", ""pullover"", ""shirt"", ""dress""], [""textured"", ""smooth"", ""ruffled"", ""embroidered""], [""bright"", ""muted"", ""dark"", ""vibrant""]]","[""muted lavender"", ""merino wool"", ""pullover"", ""smooth"", ""muted""]"
121
+ 118,"[""What color is the fabric of the shorts?"", ""What style of shorts is depicted?"", ""What type of fabric are the shorts made from?"", ""Do the shorts have a high waist design?"", ""Are the shorts depicted as tight-fitting or loose?""]","[[""blue"", ""red"", ""green"", ""yellow""], [""high-waisted"", ""low-rise"", ""cargo"", ""bermuda""], [""denim"", ""chambray"", ""cotton"", ""linen""], [""yes"", ""no""], [""tight-fitting"", ""loose"", ""skinny"", ""capri""]]","[""blue"", ""high-waisted"", ""chambray"", ""yes"", ""loose""]"
122
+ 119,"[""What color is the trench coat?"", ""Does the trench coat have a tie belt?"", ""What type of collar does the trench coat have?"", ""Are there any buttons visible on the trench coat?"", ""Is the trench coat long-sleeved or short-sleeved?""]","[[""beige"", ""black"", ""blue"", ""red""], [""yes"", ""no""], [""notched"", ""mandarin"", ""shawl"", ""collarless""], [""yes"", ""no""], [""long-sleeved"", ""short-sleeved"", ""sleeveless""]]","[""beige"", ""yes"", ""notched"", ""yes"", ""long-sleeved""]"
123
+ 120,"[""What color is the hoodie?"", ""Does the hoodie have a kangaroo pocket?"", ""What type of material is the hoodie made from?"", ""Is the hoodie designed for adults or children?"", ""What style does the hoodie depict?""]","[[""light gray"", ""dark gray"", ""black"", ""white""], [""yes"", ""no""], [""cotton"", ""fleece"", ""denim"", ""polyester""], [""adults"", ""children"", ""both"", ""neither""], [""hooded"", ""crew neck"", ""v-neck"", ""turtleneck""]]","[""light gray"", ""yes"", ""fleece"", ""adults"", ""hooded""]"
124
+ 121,"[""What type of fabric is the graphic tee made of?"", ""What style of design is featured on the tee?"", ""Is the graphic design on the tee modern or vintage?"", ""What color scheme is predominantly used in the graphic design?"", ""Does the tee have a fitted or relaxed fit?""]","[[""cotton"", ""polyester"", ""wool"", ""linen""], [""abstract"", ""vintage"", ""minimalist"", ""futuristic""], [""modern"", ""vintage""], [""bright"", ""pastel"", ""monochrome"", ""earth tones""], [""fitted"", ""relaxed"", ""oversized"", ""crop""]]","[""cotton"", ""vintage"", ""vintage"", ""earth tones"", ""relaxed""]"
125
+ 122,"[""What color is the camisole?"", ""What type of fabric is the camisole likely made of?"", ""What decorative feature is present on the camisole?"", ""Is the camisole designed to be fitted or loose?""]","[[""blush pink"", ""white"", ""black"", ""blue""], [""cotton"", ""satin"", ""denim"", ""wool""], [""lace trim"", ""ruffles"", ""buttons"", ""pockets""], [""fitted"", ""loose"", ""baggy"", ""oversized""]]","[""blush pink"", ""satin"", ""lace trim"", ""fitted""]"
126
+ 123,"[""What pattern is visible on the skirt?"", ""Does the skirt have pleats?"", ""What is the waist style of the skirt?"", ""What type of fabric is the skirt made of?"", ""Is the skirt long or short?""]","[[""solid"", ""striped"", ""plaid"", ""polka dot""], [""yes"", ""no""], [""high waist"", ""low waist"", ""mid-rise"", ""none""], [""cotton"", ""silk"", ""wool"", ""denim""], [""long"", ""short"", ""knee-length"", ""mini""]]","[""plaid"", ""yes"", ""high waist"", ""wool"", ""knee-length""]"
127
+ 124,"[""What pattern is featured on the scarf?"", ""What color scheme is used in the scarf?"", ""Is the texture of the scarf smooth or knit?"", ""What type of scarf is depicted in the image?""]","[[""stripes"", ""polka dots"", ""chevron"", ""floral""], [""bright colors"", ""shades of gray"", ""pastel colors"", ""primary colors""], [""smooth"", ""knit"", ""silky"", ""rough""], [""blanket scarf"", ""infinity scarf"", ""bandana"", ""wrap scarf""]]","[""chevron"", ""shades of gray"", ""knit"", ""blanket scarf""]"
128
+ 125,"[""What color is the shirt?"", ""Does the shirt have a collar?"", ""What type of fit does the shirt have?"", ""Are there any patterns on the shirt?"", ""What is the style of the shirt's sleeves?""]","[[""white"", ""blue"", ""black"", ""gray""], [""yes"", ""no""], [""tailored"", ""loose"", ""oversized"", ""fitted""], [""yes"", ""no""], [""short sleeves"", ""long sleeves"", ""sleeveless"", ""three-quarter sleeves""]]","[""white"", ""yes"", ""tailored"", ""no"", ""long sleeves""]"
129
+ 126,"[""What color are the chinos?"", ""What type of fit do the chinos have?"", ""What material are the chinos made from?"", ""What style are the chinos designed to represent?""]","[[""red"", ""olive green"", ""blue"", ""black""], [""loose fit"", ""slim fit"", ""regular fit"", ""baggy fit""], [""denim"", ""cotton twill"", ""polyester"", ""linen""], [""formal"", ""casual"", ""athletic"", ""business""]]","[""olive green"", ""slim fit"", ""cotton twill"", ""casual""]"
130
+ 127,"[""What type of sleeves does the dress have?"", ""What pattern is featured on the dress?"", ""What is the overall color scheme of the floral print?"", ""Is the dress designed to be long or short?"", ""Does the dress have a fitted or loose silhouette?""]","[[""cap sleeves"", ""flutter sleeves"", ""long sleeves"", ""no sleeves""], [""striped"", ""polka dot"", ""floral"", ""checkered""], [""monochrome"", ""pastel"", ""bright multicolor"", ""dark colors""], [""long"", ""short"", ""knee-length"", ""floor-length""], [""fitted"", ""loose"", ""tailored"", ""bodycon""]]","[""flutter sleeves"", ""floral"", ""bright multicolor"", ""knee-length"", ""loose""]"
131
+ 128,"[""What color are the overalls?"", ""What type of fit do the overalls have?"", ""Where are the buttons located on the overalls?"", ""What is the primary material of the overalls?""]","[[""blue"", ""black"", ""green"", ""red""], [""tight"", ""relaxed"", ""loose"", ""fitted""], [""front"", ""sides"", ""back"", ""none""], [""denim"", ""cotton"", ""polyester"", ""wool""]]","[""blue"", ""relaxed"", ""sides"", ""denim""]"
132
+ 129,"[""What color are the sandals?"", ""Do the sandals have an ankle strap?"", ""What type of heel do the sandals have?"", ""What material are the sandals made of?""]","[[""red"", ""tan"", ""black"", ""white""], [""yes"", ""no""], [""chunky"", ""stiletto"", ""flat"", ""wedge""], [""leather"", ""canvas"", ""rubber"", ""synthetic""]]","[""tan"", ""yes"", ""chunky"", ""leather""]"
133
+ 130,"[""What color is the pencil skirt?"", ""Does the skirt have a back slit?"", ""What material is the skirt made of?"", ""What is the style of the skirt?""]","[[""black"", ""blue"", ""red"", ""green""], [""yes"", ""no""], [""denim"", ""cotton"", ""faux leather"", ""silk""], [""A-line"", ""pencil"", ""pleated"", ""maxi""]]","[""black"", ""yes"", ""faux leather"", ""pencil""]"
134
+ 131,"[""What color is the turtleneck?"", ""What type of fabric is the turtleneck made of?"", ""What style of collar does the turtleneck have?"", ""Is the turtleneck fitted or loose?"", ""What is the overall tone of the turtleneck?""]","[[""black"", ""burgundy"", ""blue"", ""green""], [""wool"", ""cotton"", ""silk"", ""polyester""], [""crew neck"", ""v-neck"", ""turtleneck"", ""collarless""], [""fitted"", ""loose"", ""oversized"", ""baggy""], [""light"", ""neutral"", ""rich"", ""pastel""]]","[""burgundy"", ""cotton"", ""turtleneck"", ""fitted"", ""rich""]"
135
+ 132,"[""What color is the cardigan?"", ""What type of pockets does the cardigan have?"", ""Is the cardigan made of a soft material?"", ""What is the style of the cardigan?""]","[[""beige"", ""black"", ""red"", ""blue""], [""patch pockets"", ""zippered pockets"", ""no pockets"", ""side pockets""], [""yes"", ""no""], [""hooded"", ""cropped"", ""long-sleeve"", ""sleeveless""]]","[""beige"", ""patch pockets"", ""yes"", ""long-sleeve""]"
136
+ 133,"[""What color are the ankle boots?"", ""What type of toe do the boots have?"", ""What material are the boots made of?"", ""How high are the boots on the ankle?""]","[[""black"", ""brown"", ""red"", ""white""], [""rounded"", ""pointed"", ""square"", ""flat""], [""leather"", ""canvas"", ""suede"", ""rubber""], [""low"", ""mid"", ""high"", ""very high""]]","[""black"", ""pointed"", ""leather"", ""mid""]"
137
+ 134,"[""What color are the sneakers?"", ""What color are the soles of the sneakers?"", ""Do the sneakers have laces?"", ""What type of shoe is depicted in the image?"", ""Are the sneakers high-top or low-top?""]","[[""red"", ""yellow"", ""blue"", ""green""], [""black"", ""white"", ""brown"", ""gray""], [""yes"", ""no""], [""sandals"", ""boots"", ""sneakers"", ""loafers""], [""high-top"", ""low-top""]]","[""yellow"", ""white"", ""yes"", ""sneakers"", ""low-top""]"
138
+ 135,"[""What color is the blouse?"", ""Are there ruffled cuffs on the blouse?"", ""Is the blouse made of a shiny fabric?"", ""What type of neckline does the blouse have?"", ""Are there any patterns on the blouse?""]","[[""red"", ""blue"", ""black"", ""silk""], [""yes"", ""no""], [""yes"", ""no""], [""v-neck"", ""round"", ""collared"", ""off-shoulder""], [""floral"", ""striped"", ""solid"", ""polka dot""]]","[""silk"", ""yes"", ""yes"", ""v-neck"", ""solid""]"
139
+ 136,"[""What color is the bomber jacket?"", ""Does the jacket have ribbed cuffs?"", ""Is the jacket cropped in length?"", ""What type of jacket is depicted in the image?""]","[[""olive green"", ""black"", ""brown"", ""blue""], [""yes"", ""no""], [""yes"", ""no""], [""bomber jacket"", ""denim jacket"", ""parka"", ""trench coat""]]","[""olive green"", ""yes"", ""yes"", ""bomber jacket""]"
140
+ 137,"[""What type of pattern is featured on the dress?"", ""What is the waist style of the dress?"", ""What length is the dress?"", ""What color scheme is predominant in the floral pattern?""]","[[""striped"", ""floral"", ""polka dot"", ""geometric""], [""cinched"", ""high-waisted"", ""low-rise"", ""empire""], [""mini"", ""knee-length"", ""maxi"", ""crop""], [""pastel"", ""monochrome"", ""vibrant"", ""dark""]]","[""floral"", ""cinched"", ""maxi"", ""vibrant""]"
141
+ 138,"[""What color dominates the checkered pattern?"", ""Does the shirt have long sleeves?"", ""Is the fabric texture smooth or soft?"", ""Are there any buttons visible on the shirt?"", ""What type of collar does the shirt have?""]","[[""red"", ""blue"", ""green"", ""yellow""], [""yes"", ""no""], [""smooth"", ""soft""], [""yes"", ""no""], [""pointed"", ""rounded"", ""no collar"", ""high""]]","[""red"", ""yes"", ""soft"", ""yes"", ""pointed""]"
142
+ 139,"[""What color is the scarf?"", ""Does the scarf have fringed edges?"", ""What texture does the scarf appear to have?"", ""Is the scarf in a solid color or patterned?"", ""What is the overall style of the scarf?""]","[[""cream"", ""red"", ""blue"", ""green""], [""yes"", ""no""], [""smooth"", ""chunky"", ""silky"", ""thin""], [""solid color"", ""striped"", ""polka dot"", ""floral""], [""formal"", ""casual"", ""sporty"", ""elegant""]]","[""cream"", ""yes"", ""chunky"", ""solid color"", ""casual""]"
143
+ 140,"[""What color are the trousers?"", ""What type of cut do the trousers have?"", ""Are the trousers fitted or straight cut?"", ""Is there any visible pattern on the trousers?""]","[[""black"", ""blue"", ""grey"", ""white""], [""tapered"", ""straight"", ""bootcut"", ""flared""], [""fitted"", ""straight"", ""baggy"", ""skinny""], [""yes"", ""no""]]","[""black"", ""straight"", ""straight"", ""no""]"
144
+ 141,"[""What color is the denim jacket?"", ""Does the jacket have any pockets?"", ""What type of hem does the jacket have?"", ""Is the denim jacket styled for a casual look?""]","[[""light blue"", ""dark blue"", ""black"", ""white""], [""yes"", ""no""], [""frayed"", ""straight"", ""curved"", ""double-stitched""], [""yes"", ""no""]]","[""light blue"", ""yes"", ""frayed"", ""yes""]"
145
+ 142,"[""What color is the leather crossbody bag?"", ""Does the bag feature an adjustable strap?"", ""What type of closure does the bag have?"", ""Is there a visible logo on the bag?"", ""What is the general shape of the bag?""]","[[""black"", ""brown"", ""red"", ""blue""], [""yes"", ""no""], [""zipper"", ""button"", ""magnet"", ""snap""], [""yes"", ""no""], [""rectangle"", ""circle"", ""oval"", ""square""]]","[""brown"", ""yes"", ""zipper"", ""no"", ""rectangle""]"
146
+ 143,"[""What pattern is featured on the shirt?"", ""Are the sleeves of the shirt rolled up?"", ""What color scheme is primarily used in the shirt?"", ""Is the shirt short-sleeved or long-sleeved?""]","[[""polka dots"", ""striped"", ""plaid"", ""solid""], [""yes"", ""no""], [""monochrome"", ""pastel"", ""bright colors"", ""neutral tones""], [""short-sleeved"", ""long-sleeved""]]","[""striped"", ""yes"", ""neutral tones"", ""long-sleeved""]"
147
+ 144,"[""What type of skirt is depicted in the image?"", ""What color palette is primarily used in the watercolor print?"", ""Does the skirt have a defined waistline or is it more flowy?"", ""Are there any patterns or designs visible in the watercolor print?"", ""Is the skirt knee-length, ankle-length, or floor-length?""]","[[""pencil skirt"", ""midi skirt"", ""maxi skirt"", ""mini skirt""], [""pastels"", ""neon colors"", ""monochrome"", ""earth tones""], [""defined waistline"", ""flowy"", ""tight fit"", ""structured""], [""floral"", ""geometric"", ""abstract"", ""solid color""], [""knee-length"", ""ankle-length"", ""floor-length"", ""short""]]","[""midi skirt"", ""pastels"", ""flowy"", ""floral"", ""ankle-length""]"
148
+ 145,"[""What color is the t-shirt?"", ""What type of neck does the t-shirt have?"", ""What fabric style is the t-shirt made of?"", ""Is the t-shirt short-sleeved or long-sleeved?""]","[[""pastel pink"", ""blue"", ""green"", ""black""], [""crew neck"", ""v-neck"", ""collar"", ""scoop neck""], [""denim"", ""soft jersey"", ""cotton"", ""silk""], [""short-sleeved"", ""long-sleeved"", ""sleeveless"", ""three-quarter sleeve""]]","[""pastel pink"", ""crew neck"", ""soft jersey"", ""short-sleeved""]"
149
+ 146,"[""What color is the beanie?"", ""What texture is visible on the beanie?"", ""Is the beanie fitted or slouchy in style?"", ""Are there any visible patterns on the beanie?""]","[[""charcoal gray"", ""black"", ""light gray"", ""navy blue""], [""ribbed"", ""smooth"", ""floral"", ""polka dot""], [""fitted"", ""slouchy"", ""bucket"", ""visor""], [""yes"", ""no""]]","[""charcoal gray"", ""ribbed"", ""slouchy"", ""no""]"
150
+ 147,"[""What color is the sweater?"", ""What type of fabric is the sweater made of?"", ""What is the general style of the sweater?"", ""Are there any patterns on the sweater?"", ""What type of neckline does the sweater have?""]","[[""red"", ""navy blue"", ""green"", ""black""], [""cotton"", ""wool"", ""cashmere"", ""linen""], [""casual"", ""formal"", ""sporty"", ""business""], [""stripes"", ""plaid"", ""solid"", ""floral""], [""crew neck"", ""v-neck"", ""turtleneck"", ""scoop neck""]]","[""navy blue"", ""cashmere"", ""casual"", ""solid"", ""crew neck""]"
151
+ 148,"[""What color are the jeans?"", ""What style of jeans is depicted?"", ""Do the jeans have a high waist?"", ""What type of wash do the jeans have?"", ""Are there any embellishments on the jeans?""]","[[""light wash"", ""dark wash"", ""medium wash"", ""black""], [""skinny"", ""high-waisted"", ""bootcut"", ""flared""], [""yes"", ""no""], [""distressed"", ""dark wash"", ""acid wash"", ""faded""], [""yes"", ""no""]]","[""dark wash"", ""high-waisted"", ""yes"", ""dark wash"", ""no""]"
152
+ 149,"[""What color is the sundress?"", ""What type of skirt does the dress have?"", ""Is the sundress patterned or solid?"", ""What is the overall style of the dress?""]","[[""red"", ""yellow"", ""blue"", ""green""], [""flared"", ""straight"", ""pencil"", ""A-line""], [""patterned"", ""solid"", ""striped"", ""polka-dotted""], [""casual"", ""formal"", ""athletic"", ""business""]]","[""yellow"", ""flared"", ""solid"", ""casual""]"
153
+ 150,"[""What color is primarily seen on the denim jacket?"", ""Does the jacket have any visible distressing features?"", ""Is the finish of the jacket shiny or faded?"", ""What type of closure does the jacket likely have?"", ""Are there any additional elements like patches or embroidery on the jacket?""]","[[""blue"", ""black"", ""red"", ""green""], [""yes"", ""no""], [""shiny"", ""faded""], [""buttons"", ""zippers"", ""velcro"", ""none""], [""yes"", ""no""]]","[""blue"", ""yes"", ""faded"", ""buttons"", ""no""]"
154
+ 151,"[""What color is the parka?"", ""Does the parka have a hood?"", ""Are there drawstrings on the parka?"", ""What type of clothing is depicted in the image?""]","[[""red"", ""navy"", ""green"", ""black""], [""yes"", ""no""], [""yes"", ""no""], [""jacket"", ""dress"", ""parka"", ""shirt""]]","[""navy"", ""yes"", ""yes"", ""parka""]"
155
+ 152,"[""What color are the trousers?"", ""What material do the trousers appear to be made of?"", ""Are the trousers designed with any specific texture?"", ""What is the style of the trousers?""]","[[""metallic gold"", ""silver"", ""black"", ""white""], [""satin"", ""denim"", ""cotton"", ""leather""], [""pleated"", ""smooth"", ""ruffled"", ""fuzzy""], [""skinny"", ""wide-leg"", ""pleated"", ""cargo""]]","[""metallic gold"", ""satin"", ""pleated"", ""pleated""]"
156
+ 153,"[""What color are the jeans depicted in the image?"", ""Are there any visible rips or tears in the jeans?"", ""What is the overall fit of the jeans?"", ""What style of jeans is shown in the image?""]","[[""blue"", ""black"", ""white"", ""green""], [""yes"", ""no""], [""tight"", ""relaxed"", ""baggy"", ""skinny""], [""distressed boyfriend"", ""skinny"", ""straight"", ""wide-leg""]]","[""blue"", ""yes"", ""relaxed"", ""distressed boyfriend""]"
157
+ 154,"[""What color is the beanie?"", ""Does the beanie have a cuffed edge?"", ""What is the style of the beanie?"", ""Is the beanie textured or smooth?""]","[[""forest green"", ""black"", ""navy blue"", ""red""], [""yes"", ""no""], [""slouchy"", ""cuffed"", ""beanie hat"", ""bucket hat""], [""textured"", ""smooth"", ""striped"", ""polka-dotted""]]","[""forest green"", ""yes"", ""cuffed"", ""smooth""]"
158
+ 155,"[""What type of fabric is featured in the leggings?"", ""Are the leggings designed for a specific activity?"", ""Is there a visible mesh panel in the design?"", ""What color are the leggings predominantly?"", ""Do the leggings have a high waistband?""]","[[""cotton"", ""mesh"", ""denim"", ""silk""], [""yes"", ""no""], [""yes"", ""no""], [""black"", ""blue"", ""green"", ""red""], [""yes"", ""no""]]","[""mesh"", ""yes"", ""yes"", ""black"", ""yes""]"
159
+ 156,"[""What color is the bold graphic print on the tote bag?"", ""Is the tote bag made of a soft or rigid material?"", ""What type of graphic elements can be seen on the tote bag?"", ""Does the tote bag have handles?"", ""Is the graphic print on the tote bag simple or intricate?""]","[[""red"", ""blue"", ""black"", ""green""], [""soft"", ""rigid""], [""text"", ""geometric shapes"", ""floral patterns"", ""abstract designs""], [""yes"", ""no""], [""simple"", ""intricate""]]","[""blue"", ""soft"", ""geometric shapes"", ""yes"", ""intricate""]"
160
+ 157,"[""What color is the top?"", ""Does the top have long sleeves?"", ""Is there a tie detail in the design?"", ""What is the style of the top?"", ""Is the fabric of the top described as textured?""]","[[""white"", ""black"", ""blue"", ""red""], [""yes"", ""no""], [""yes"", ""no""], [""wrap"", ""t-shirt"", ""tank"", ""hoodie""], [""yes"", ""no""]]","[""white"", ""yes"", ""yes"", ""wrap"", ""no""]"
161
+ 158,"[""What type of dress is depicted in the image?"", ""What pattern is featured on the dress?"", ""How does the hem of the dress appear?"", ""What color scheme is likely present in the animal print?""]","[[""maxi dress"", ""midi dress"", ""mini dress"", ""short dress""], [""floral"", ""geometric"", ""animal print"", ""solid color""], [""straight"", ""flowy"", ""asymmetrical"", ""ruffled""], [""monochrome"", ""vibrant colors"", ""pastel colors"", ""earth tones""]]","[""midi dress"", ""animal print"", ""flowy"", ""vibrant colors""]"
162
+ 159,"[""What color are the tailored shorts?"", ""Does the image show a visible zipper?"", ""What is the style of the shorts depicted?"", ""Are there any patterns on the shorts?""]","[[""white"", ""black"", ""blue"", ""red""], [""yes"", ""no""], [""tailored"", ""baggy"", ""cargo"", ""running""], [""yes"", ""no""]]","[""white"", ""no"", ""tailored"", ""no""]"
163
+ 160,"[""What color is the blazer?"", ""What type of clothing is depicted in the image?"", ""Does the blazer have any visible buttons?"", ""What style of the blazer is represented?""]","[[""burgundy"", ""navy"", ""black"", ""green""], [""sweater"", ""blazer"", ""shirt"", ""coat""], [""yes"", ""no""], [""fitted"", ""loose"", ""oversized"", ""crop""]]","[""burgundy"", ""blazer"", ""yes"", ""fitted""]"
164
+ 161,"[""What color is the vest?"", ""What type of pockets does the vest have?"", ""Is the vest designed with a pattern?"", ""What is the style of the vest?""]","[[""blue"", ""green"", ""bright red"", ""black""], [""zip pockets"", ""button pockets"", ""no pockets""], [""striped"", ""plaid"", ""quilted"", ""polka dot""], [""puffer"", ""sleeveless"", ""long-sleeved"", ""hooded""]]","[""bright red"", ""zip pockets"", ""quilted"", ""puffer""]"
165
+ 162,"[""What is the primary color of the scarf?"", ""What is the color of the spots on the scarf?"", ""What pattern is featured on the scarf?"", ""Is the scarf made of a patterned fabric?"", ""Does the scarf have a solid color background?""]","[[""red"", ""navy"", ""green"", ""black""], [""blue"", ""white"", ""red"", ""yellow""], [""stripes"", ""polka dots"", ""plaid"", ""floral""], [""yes"", ""no""], [""yes"", ""no""]]","[""navy"", ""white"", ""polka dots"", ""yes"", ""no""]"
166
+ 163,"[""What is the primary fabric of the kimono?"", ""How would you describe the sleeves of the kimono?"", ""What type of pattern is featured on the kimono?"", ""Is the kimono designed to be fitted or loose?"", ""What color scheme is likely present in the floral chiffon?""]","[[""silk"", ""cotton"", ""chiffon"", ""wool""], [""narrow"", ""wide"", ""long"", ""short""], [""striped"", ""floral"", ""solid"", ""geometric""], [""fitted"", ""loose"", ""tailored"", ""structured""], [""monochrome"", ""pastel"", ""bold"", ""neon""]]","[""chiffon"", ""wide"", ""floral"", ""loose"", ""pastel""]"
data/gen_descriptions.py ADDED
@@ -0,0 +1,245 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import openai
2
+ import pandas as pd
3
+ import random
4
+ import string
5
+ import os
6
+ from typing import List, Dict
7
+ import argparse
8
+ from dotenv import load_dotenv
9
+
10
+ starting_id = 0
11
+ def new_id() -> int:
12
+ """Return a new ID that is the next integer in the sequence"""
13
+ global starting_id
14
+ temp = starting_id
15
+ starting_id += 1
16
+ return temp
17
+
18
+ def setup_openai_client(api_key: str):
19
+ """Set up and return an OpenAI client."""
20
+ client = openai.OpenAI(api_key=api_key)
21
+ return client
22
+
23
+ def read_existing_descriptions(file_path: str) -> set:
24
+ """Read and return existing descriptions from a CSV file using pandas."""
25
+ if not os.path.exists(file_path):
26
+ return set()
27
+
28
+ df = pd.read_csv(file_path)
29
+ if 'description' in df.columns:
30
+ return set(df['description'].str.lower())
31
+ return set()
32
+
33
+ def get_prompt_for_category(category: str, count: int, max_length: int, target_avg_length: int) -> str:
34
+ """Return a specific prompt based on the category."""
35
+
36
+ if category == "landscapes":
37
+ return f"""
38
+ Generate {count} short, generic descriptions of landscapes.
39
+
40
+ Requirements:
41
+ Each landscape description should be concise, around {target_avg_length} characters on average
42
+ No description should exceed {max_length} characters
43
+ Do NOT include any brand names, trademarks, or personal names
44
+ Do NOT include any people, even generically
45
+ Descriptions should be varied and creative
46
+ Only provide the descriptions, one per line, with no numbering or additional text
47
+ Focus on natural scenes, vistas, and environments
48
+
49
+ Examples:
50
+ a purple forest at dusk
51
+ a lighthouse overlooking the ocean
52
+ a green lagoon under a cloudy sky
53
+ a snowy plain
54
+ a starlit night over snow-covered peaks
55
+ """
56
+
57
+ elif category == "abstract":
58
+ return f"""
59
+ Generate {count} short, generic descriptions of abstract art or geometric compositions.
60
+
61
+ Requirements:
62
+ Each abstract description should be concise, around {target_avg_length} characters on average
63
+ No description should exceed {max_length} characters
64
+ Do NOT include any brand names, trademarks, or personal names
65
+ Focus on geometric shapes, patterns, and colors
66
+ Be creative with color combinations and spatial arrangements
67
+ Only provide the descriptions, one per line, with no numbering or additional text
68
+
69
+ Examples:
70
+ crimson rectangles forming a chaotic grid
71
+ purple pyramids spiraling around a bronze cone
72
+ magenta trapezoids layered on a transluscent silver sheet
73
+ khaki triangles and azure crescents
74
+ a maroon dodecahedron interwoven with teal threads
75
+ """
76
+
77
+ elif category == "fashion":
78
+ return f"""
79
+ Generate {count} short, generic descriptions of fashion items and clothing.
80
+
81
+ Requirements:
82
+ Each fashion description should be concise, around {target_avg_length} characters on average
83
+ No description should exceed {max_length} characters
84
+ Do NOT include any brand names, trademarks, or personal names
85
+ Do NOT include any people, even generically
86
+ Focus on clothing items, accessories, fabrics, patterns, and colors
87
+ Be specific about materials, cuts, and design features
88
+ Only provide the descriptions, one per line, with no numbering or additional text
89
+
90
+ Examples:
91
+ gray wool coat with a faux fur collar
92
+ burgundy corduroy pants with patch pockets and silver buttons
93
+ orange corduroy overalls
94
+ a purple silk scarf with tassel trim
95
+ black and white checkered pants
96
+ """
97
+
98
+ else:
99
+ # Generic prompt for additional categories
100
+ return f"""
101
+ Generate {count} short, generic descriptions of {category}.
102
+
103
+ Requirements:
104
+ - Each description should be concise, around {target_avg_length} characters on average
105
+ - No description should exceed {max_length} characters
106
+ - Do NOT include any brand names, trademarks, or personal names
107
+ - Do NOT include any people, even generically
108
+ - Descriptions should be varied and creative
109
+ - Only provide the descriptions, one per line, with no numbering or additional text
110
+ """
111
+
112
+ def generate_descriptions(
113
+ client,
114
+ categories: List[str],
115
+ count_per_category: int,
116
+ max_length: int = 200,
117
+ target_avg_length: int = 50,
118
+ existing_descriptions: set = set()
119
+ ) -> Dict[str, List[str]]:
120
+ """Generate descriptions for each category using GPT-4o mini with separate prompts."""
121
+
122
+ results = {category: [] for category in categories}
123
+
124
+ for category in categories:
125
+ print(f"Generating {count_per_category} descriptions for category: {category}")
126
+
127
+ # Get the specific prompt for this category
128
+ system_prompt = get_prompt_for_category(
129
+ category=category,
130
+ count=count_per_category,
131
+ max_length=max_length,
132
+ target_avg_length=target_avg_length
133
+ )
134
+
135
+ unique_descriptions = set()
136
+
137
+ try:
138
+ while len(unique_descriptions) < count_per_category:
139
+ remaining = count_per_category - len(unique_descriptions)
140
+ print(f"Generating {remaining} more unique descriptions for {category}...")
141
+
142
+ # Make the API call
143
+ response = client.chat.completions.create(
144
+ model="gpt-4o-mini", # Using GPT-4o mini as requested
145
+ messages=[
146
+ {"role": "system", "content": system_prompt},
147
+ {"role": "user", "content": f"Generate {remaining} {category} descriptions."}
148
+ ],
149
+ temperature=0.7,
150
+ max_tokens=8000
151
+ )
152
+
153
+ # Process the response
154
+ content = response.choices[0].message.content
155
+ descriptions = [line.strip() for line in content.split('\n') if line.strip()]
156
+
157
+ # Filter out any descriptions that are too long, already existing, or duplicates
158
+ for desc in descriptions:
159
+ desc_lower = desc.lower()
160
+ if (len(desc) <= max_length and
161
+ desc_lower not in {d.lower() for d in unique_descriptions} and
162
+ desc_lower not in existing_descriptions):
163
+ unique_descriptions.add(desc)
164
+
165
+ if len(unique_descriptions) >= count_per_category:
166
+ break
167
+
168
+ # Convert to list
169
+ results[category] = list(unique_descriptions)
170
+
171
+ except Exception as e:
172
+ print(f"Error generating descriptions for {category}: {e}")
173
+
174
+ return results
175
+
176
+ def write_to_csv_pandas(
177
+ descriptions_dict: Dict[str, List[str]],
178
+ output_file: str,
179
+ append: bool = False
180
+ ) -> None:
181
+ """Write or append the generated descriptions to a CSV file using pandas."""
182
+
183
+ # Create a list of dictionaries for our new data
184
+ data = []
185
+ for category, descriptions in descriptions_dict.items():
186
+ for description in descriptions:
187
+ data.append({
188
+ "id": new_id(),
189
+ "description": description,
190
+ "category": category
191
+ })
192
+
193
+ # Create a DataFrame from our data
194
+ new_df = pd.DataFrame(data)
195
+
196
+ # Append or create new file
197
+ if append and os.path.exists(output_file):
198
+ existing_df = pd.read_csv(output_file)
199
+ combined_df = pd.concat([existing_df, new_df], ignore_index=True)
200
+ combined_df.to_csv(output_file, index=False)
201
+ print(f"Appended {len(new_df)} descriptions to {output_file}")
202
+ else:
203
+ new_df.to_csv(output_file, index=False)
204
+ print(f"Wrote {len(new_df)} descriptions to {output_file}")
205
+
206
+ def main():
207
+ csv_path = "data/descriptions.csv"
208
+ output_file = "data/descriptions.csv"
209
+ append = True
210
+ count = 50
211
+ categories = ["landscapes", "abstract", "fashion"]
212
+
213
+ load_dotenv()
214
+ api_key = os.getenv("OPENAI_API_KEY")
215
+ if api_key is None:
216
+ raise ValueError("OPENAI_API_KEY is not set")
217
+
218
+ # Set up the OpenAI client
219
+ client = setup_openai_client(api_key)
220
+
221
+ # If appending, read existing descriptions to avoid duplicates
222
+ existing_descriptions = set()
223
+ if append and os.path.exists(csv_path):
224
+ global starting_id
225
+ starting_id = pd.read_csv(csv_path)["id"].max()
226
+ existing_descriptions = read_existing_descriptions(csv_path)
227
+ print(f"Found {len(existing_descriptions)} existing descriptions")
228
+
229
+ # Generate the descriptions
230
+ descriptions_dict = generate_descriptions(
231
+ client=client,
232
+ categories=categories,
233
+ count_per_category=count,
234
+ existing_descriptions=existing_descriptions
235
+ )
236
+
237
+ # Write to CSV using pandas
238
+ write_to_csv_pandas(
239
+ descriptions_dict=descriptions_dict,
240
+ output_file=output_file,
241
+ append=append
242
+ )
243
+
244
+ if __name__ == "__main__":
245
+ main()
data/gen_vqa.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import json
3
+ import time
4
+ import os
5
+ from openai import OpenAI
6
+ from tqdm import tqdm # for progress bar
7
+ import dotenv
8
+
9
+ dotenv.load_dotenv()
10
+
11
+ # Initialize OpenAI client
12
+ api_key = os.environ.get("OPENAI_API_KEY")
13
+ if not api_key:
14
+ api_key = input("Enter your OpenAI API key: ")
15
+ client = OpenAI(api_key=api_key)
16
+
17
+ def generate_evaluation_data(description):
18
+ """
19
+ Use GPT-4o mini to generate evaluation questions, choices, and answers for an SVG image description
20
+ """
21
+ prompt = f"""
22
+ Based on the following description of an SVG image:
23
+ "{description}"
24
+
25
+ Generate 3-5 questions about visual elements that would be in this image, along with multiple-choice options and the correct answers.
26
+
27
+ For each question:
28
+ 1. The question should be answerable by looking at the image that matches the description
29
+ 2. Provide 2-4 possible answer choices for each question
30
+ 3. Indicate the correct answer that matches the description
31
+
32
+ Format your response as a JSON object with exactly these three keys:
33
+ - "question": a list of question strings
34
+ - "choices": a list of lists, where each inner list contains the possible choices for the corresponding question
35
+ - "answer": a list of strings, where each string is the correct answer for the corresponding question
36
+
37
+ Example format:
38
+ {{
39
+ "question": ["Is there a red circle?", "What shape is present?"],
40
+ "choices": [["yes", "no"], ["square", "circle", "triangle", "hexagon"]],
41
+ "answer": ["yes", "circle"]
42
+ }}
43
+
44
+ Make sure your response is strictly in this JSON format with no additional text.
45
+ """
46
+
47
+ try:
48
+ response = client.chat.completions.create(
49
+ model="gpt-4o-mini",
50
+ messages=[{"role": "user", "content": prompt}],
51
+ temperature=0.7,
52
+ max_tokens=1000,
53
+ response_format={"type": "json_object"}
54
+ )
55
+
56
+ # Parse the JSON response
57
+ result = json.loads(response.choices[0].message.content)
58
+
59
+ # Validate the response structure
60
+ if not all(key in result for key in ["question", "choices", "answer"]):
61
+ print(f"Warning: Response missing required keys for '{description}'")
62
+ return None
63
+
64
+ # Check that all lists are the same length
65
+ if not (len(result["question"]) == len(result["choices"]) == len(result["answer"])):
66
+ print(f"Warning: Lists in response have inconsistent lengths for '{description}'")
67
+ return None
68
+
69
+ return result
70
+
71
+ except Exception as e:
72
+ print(f"Error generating evaluation data for '{description}': {e}")
73
+ return None
74
+
75
+ def create_evaluation_dataset(csv_path, output_path):
76
+ """
77
+ Process a CSV file with descriptions and create an evaluation dataset
78
+ """
79
+ # Read the CSV file
80
+ df = pd.read_csv(csv_path)
81
+ print(f"Loaded {len(df)} descriptions from {csv_path}")
82
+
83
+ # Initialize lists to store the evaluation data
84
+ ids = []
85
+ questions = []
86
+ choices = []
87
+ answers = []
88
+
89
+ # Process each row in the CSV
90
+ for _, row in tqdm(df.iterrows(), total=len(df), desc="Processing descriptions"):
91
+ item_id = row["id"]
92
+ description = row["description"]
93
+
94
+ # Generate evaluation data
95
+ eval_data = generate_evaluation_data(description)
96
+
97
+ if eval_data:
98
+ ids.append(item_id)
99
+ questions.append(json.dumps(eval_data["question"]))
100
+ choices.append(json.dumps(eval_data["choices"]))
101
+ answers.append(json.dumps(eval_data["answer"]))
102
+
103
+ # Sleep briefly to avoid hitting API rate limits
104
+ time.sleep(0.5)
105
+
106
+ # Create a DataFrame with the evaluation data
107
+ eval_df = pd.DataFrame({
108
+ "id": ids,
109
+ "question": questions,
110
+ "choices": choices,
111
+ "answer": answers
112
+ })
113
+
114
+ # Save as CSV
115
+ eval_df.to_csv(output_path, index=False)
116
+ print(f"CSV version saved to {output_path}")
117
+
118
+ return eval_df
119
+
120
+ def main():
121
+ # Get input/output paths
122
+ input_path = "data/descriptions.csv"
123
+ output_path = "data/eval.csv"
124
+
125
+ # Create the evaluation dataset
126
+ eval_df = create_evaluation_dataset(input_path, output_path)
127
+
128
+ # Display sample of the generated dataset
129
+ print("\nSample of generated evaluation data:")
130
+ print(eval_df.head())
131
+
132
+ # Show stats
133
+ print(f"\nGenerated evaluation data for {len(eval_df)} out of {pd.read_csv(input_path).shape[0]} descriptions")
134
+
135
+ if __name__ == "__main__":
136
+ main()
improved-aesthetic-predictor/F5WsLD0XoAAviiV (1).jpeg ADDED
improved-aesthetic-predictor/LICENSE ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
improved-aesthetic-predictor/README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CLIP+MLP Aesthetic Score Predictor
2
+
3
+ Train, use and visualize an aesthetic score predictor ( how much people like on average an image ) based on a simple neural net that takes CLIP embeddings as inputs.
4
+
5
+
6
+ Link to the AVA training data ( already prepared) :
7
+ https://drive.google.com/drive/folders/186XiniJup5Rt9FXsHiAGWhgWz-nmCK_r?usp=sharing
8
+
9
+
10
+ Visualizations of all images from LAION 5B (english subset with 2.37B images) in 40 buckets with the model sac+logos+ava1-l14-linearMSE.pth:
11
+ http://captions.christoph-schuhmann.de/aesthetic_viz_laion_sac+logos+ava1-l14-linearMSE-en-2.37B.html
12
+
13
+
improved-aesthetic-predictor/prepare-data-for-training.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # This script prepares the training images and ratings for the training.
3
+ # It assumes that all images are stored as files that PIL can read.
4
+ # It also assumes that the paths to the images files and the average ratings are in a .parquet files that can be read into a dataframe ( df ).
5
+
6
+ from datasets import load_dataset
7
+ import pandas as pd
8
+ import statistics
9
+ from torch.utils.data import Dataset, DataLoader
10
+ import clip
11
+ import torch
12
+ from PIL import Image, ImageFile
13
+ import numpy as np
14
+ import time
15
+
16
+ def normalized(a, axis=-1, order=2):
17
+ import numpy as np # pylint: disable=import-outside-toplevel
18
+
19
+ l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
20
+ l2[l2 == 0] = 1
21
+ return a / np.expand_dims(l2, axis)
22
+
23
+
24
+
25
+ device = "cuda" if torch.cuda.is_available() else "cpu"
26
+ model, preprocess = clip.load("ViT-L/14", device=device)
27
+
28
+
29
+ f = "trainingdata.parquet"
30
+ df = pd.read_parquet(f) #assumes that the df has the columns IMAGEPATH & AVERAGE_RATING
31
+
32
+
33
+ x = []
34
+ y = []
35
+ c= 0
36
+
37
+ for idx, row in df.iterrows():
38
+ start = time.time()
39
+
40
+ average_rating = float(row.AVERAGE_RATING)
41
+ print(average_rating)
42
+ if average_rating <1:
43
+ continue
44
+
45
+ img= row.IMAGEPATH #assumes that the df has the column IMAGEPATH
46
+ print(img)
47
+
48
+ try:
49
+ image = preprocess(Image.open(img)).unsqueeze(0).to(device)
50
+ except:
51
+ continue
52
+
53
+ with torch.no_grad():
54
+ image_features = model.encode_image(image)
55
+
56
+ im_emb_arr = image_features.cpu().detach().numpy()
57
+ x.append(normalized ( im_emb_arr) ) # all CLIP embeddings are getting normalized. This also has to be done when inputting an embedding later for inference
58
+ y_ = np.zeros((1, 1))
59
+ y_[0][0] = average_rating
60
+ #y_[0][1] = stdev # I initially considered also predicting the standard deviation, but then didn't do it
61
+
62
+ y.append(y_)
63
+
64
+
65
+ print(c)
66
+ c+=1
67
+
68
+
69
+
70
+
71
+ x = np.vstack(x)
72
+ y = np.vstack(y)
73
+ print(x.shape)
74
+ print(y.shape)
75
+ np.save('x_OpenAI_CLIP_L14_embeddings.npy', x)
76
+ np.save('y_ratings.npy', y)
improved-aesthetic-predictor/simple_inference.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import webdataset as wds
2
+ from PIL import Image
3
+ import io
4
+ import matplotlib.pyplot as plt
5
+ import os
6
+ import json
7
+
8
+ from warnings import filterwarnings
9
+
10
+
11
+ # os.environ["CUDA_VISIBLE_DEVICES"] = "0" # choose GPU if you are on a multi GPU server
12
+ import numpy as np
13
+ import torch
14
+ import pytorch_lightning as pl
15
+ import torch.nn as nn
16
+ from torchvision import datasets, transforms
17
+ import tqdm
18
+
19
+ from os.path import join
20
+ from datasets import load_dataset
21
+ import pandas as pd
22
+ from torch.utils.data import Dataset, DataLoader
23
+ import json
24
+
25
+ import clip
26
+
27
+
28
+ from PIL import Image, ImageFile
29
+
30
+
31
+ ##### This script will predict the aesthetic score for this image file:
32
+
33
+ img_path = "test.jpg"
34
+
35
+
36
+
37
+
38
+
39
+ # if you changed the MLP architecture during training, change it also here:
40
+ class MLP(pl.LightningModule):
41
+ def __init__(self, input_size, xcol='emb', ycol='avg_rating'):
42
+ super().__init__()
43
+ self.input_size = input_size
44
+ self.xcol = xcol
45
+ self.ycol = ycol
46
+ self.layers = nn.Sequential(
47
+ nn.Linear(self.input_size, 1024),
48
+ #nn.ReLU(),
49
+ nn.Dropout(0.2),
50
+ nn.Linear(1024, 128),
51
+ #nn.ReLU(),
52
+ nn.Dropout(0.2),
53
+ nn.Linear(128, 64),
54
+ #nn.ReLU(),
55
+ nn.Dropout(0.1),
56
+
57
+ nn.Linear(64, 16),
58
+ #nn.ReLU(),
59
+
60
+ nn.Linear(16, 1)
61
+ )
62
+
63
+ def forward(self, x):
64
+ return self.layers(x)
65
+
66
+ def training_step(self, batch, batch_idx):
67
+ x = batch[self.xcol]
68
+ y = batch[self.ycol].reshape(-1, 1)
69
+ x_hat = self.layers(x)
70
+ loss = F.mse_loss(x_hat, y)
71
+ return loss
72
+
73
+ def validation_step(self, batch, batch_idx):
74
+ x = batch[self.xcol]
75
+ y = batch[self.ycol].reshape(-1, 1)
76
+ x_hat = self.layers(x)
77
+ loss = F.mse_loss(x_hat, y)
78
+ return loss
79
+
80
+ def configure_optimizers(self):
81
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
82
+ return optimizer
83
+
84
+ def normalized(a, axis=-1, order=2):
85
+ import numpy as np # pylint: disable=import-outside-toplevel
86
+
87
+ l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
88
+ l2[l2 == 0] = 1
89
+ return a / np.expand_dims(l2, axis)
90
+
91
+
92
+ model = MLP(768) # CLIP embedding dim is 768 for CLIP ViT L 14
93
+
94
+ s = torch.load("sac+logos+ava1-l14-linearMSE.pth") # load the model you trained previously or the model available in this repo
95
+
96
+ model.load_state_dict(s)
97
+
98
+ model.to("cuda")
99
+ model.eval()
100
+
101
+
102
+ device = "cuda" if torch.cuda.is_available() else "cpu"
103
+ model2, preprocess = clip.load("ViT-L/14", device=device) #RN50x64
104
+
105
+
106
+ pil_image = Image.open(img_path)
107
+
108
+ image = preprocess(pil_image).unsqueeze(0).to(device)
109
+
110
+
111
+
112
+ with torch.no_grad():
113
+ image_features = model2.encode_image(image)
114
+
115
+ im_emb_arr = normalized(image_features.cpu().detach().numpy() )
116
+
117
+ prediction = model(torch.from_numpy(im_emb_arr).to(device).type(torch.cuda.FloatTensor))
118
+
119
+ print( "Aesthetic score predicted by the model:")
120
+ print( prediction )
121
+
122
+
improved-aesthetic-predictor/train_predictor.py ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ # os.environ['CUDA_VISIBLE_DEVICES'] = "0" # in case you are using a multi GPU workstation, choose your GPU here
3
+ import tqdm
4
+ import pytorch_lightning as pl
5
+ import torch
6
+ import torch.nn as nn
7
+ from torch.utils.data import DataLoader
8
+ import torch.nn.functional as F
9
+ import pandas as pd
10
+ from datasets import load_dataset
11
+ from torch.utils.data import TensorDataset, DataLoader
12
+
13
+ import numpy as np
14
+
15
+ #define your neural net here:
16
+
17
+ class MLP(pl.LightningModule):
18
+ def __init__(self, input_size, xcol='emb', ycol='avg_rating'):
19
+ super().__init__()
20
+ self.input_size = input_size
21
+ self.xcol = xcol
22
+ self.ycol = ycol
23
+ self.layers = nn.Sequential(
24
+ nn.Linear(self.input_size, 1024),
25
+ #nn.ReLU(),
26
+ nn.Dropout(0.2),
27
+ nn.Linear(1024, 128),
28
+ #nn.ReLU(),
29
+ nn.Dropout(0.2),
30
+ nn.Linear(128, 64),
31
+ #nn.ReLU(),
32
+ nn.Dropout(0.1),
33
+
34
+ nn.Linear(64, 16),
35
+ #nn.ReLU(),
36
+
37
+ nn.Linear(16, 1)
38
+ )
39
+
40
+ def forward(self, x):
41
+ return self.layers(x)
42
+
43
+ def training_step(self, batch, batch_idx):
44
+ x = batch[self.xcol]
45
+ y = batch[self.ycol].reshape(-1, 1)
46
+ x_hat = self.layers(x)
47
+ loss = F.mse_loss(x_hat, y)
48
+ return loss
49
+
50
+ def validation_step(self, batch, batch_idx):
51
+ x = batch[self.xcol]
52
+ y = batch[self.ycol].reshape(-1, 1)
53
+ x_hat = self.layers(x)
54
+ loss = F.mse_loss(x_hat, y)
55
+ return loss
56
+
57
+ def configure_optimizers(self):
58
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
59
+ return optimizer
60
+
61
+
62
+
63
+ # load the training data
64
+
65
+ x = np.load ("/mnt/spirit/ava_x.npy")
66
+
67
+ y = np.load ("/mnt/spirit/ava_y.npy")
68
+
69
+ val_percentage = 0.05 # 5% of the trainingdata will be used for validation
70
+
71
+ train_border = int(x.shape()[0] * (1 - val_percentage) )
72
+
73
+ train_tensor_x = torch.Tensor(x[:train_border]) # transform to torch tensor
74
+ train_tensor_y = torch.Tensor(y[:train_border])
75
+
76
+ train_dataset = TensorDataset(train_tensor_x,train_tensor_y) # create your datset
77
+ train_loader = DataLoader(train_dataset, batch_size=256, shuffle=True, num_workers=16) # create your dataloader
78
+
79
+
80
+ val_tensor_x = torch.Tensor(x[train_border:]) # transform to torch tensor
81
+ val_tensor_y = torch.Tensor(y[train_border:])
82
+
83
+ '''
84
+ print(train_tensor_x.size())
85
+ print(val_tensor_x.size())
86
+ print( val_tensor_x.dtype)
87
+ print( val_tensor_x[0].dtype)
88
+ '''
89
+
90
+ val_dataset = TensorDataset(val_tensor_x,val_tensor_y) # create your datset
91
+ val_loader = DataLoader(val_dataset, batch_size=512, num_workers=16) # create your dataloader
92
+
93
+
94
+
95
+
96
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
97
+
98
+ model = MLP(768).to(device) # CLIP embedding dim is 768 for CLIP ViT L 14
99
+
100
+ optimizer = torch.optim.Adam(model.parameters())
101
+
102
+ # choose the loss you want to optimze for
103
+ criterion = nn.MSELoss()
104
+ criterion2 = nn.L1Loss()
105
+
106
+ epochs = 50
107
+
108
+ model.train()
109
+ best_loss =999
110
+ save_name = "linear_predictor_L14_MSE.pth"
111
+
112
+
113
+ for epoch in range(epochs):
114
+ losses = []
115
+ losses2 = []
116
+ for batch_num, input_data in enumerate(train_loader):
117
+ optimizer.zero_grad()
118
+ x, y = input_data
119
+ x = x.to(device).float()
120
+ y = y.to(device)
121
+
122
+ output = model(x)
123
+ loss = criterion(output, y)
124
+ loss.backward()
125
+ losses.append(loss.item())
126
+
127
+
128
+ optimizer.step()
129
+
130
+ if batch_num % 1000 == 0:
131
+ print('\tEpoch %d | Batch %d | Loss %6.2f' % (epoch, batch_num, loss.item()))
132
+ #print(y)
133
+
134
+ print('Epoch %d | Loss %6.2f' % (epoch, sum(losses)/len(losses)))
135
+ losses = []
136
+ losses2 = []
137
+
138
+ for batch_num, input_data in enumerate(val_loader):
139
+ optimizer.zero_grad()
140
+ x, y = input_data
141
+ x = x.to(device).float()
142
+ y = y.to(device)
143
+
144
+ output = model(x)
145
+ loss = criterion(output, y)
146
+ lossMAE = criterion2(output, y)
147
+ #loss.backward()
148
+ losses.append(loss.item())
149
+ losses2.append(lossMAE.item())
150
+ #optimizer.step()
151
+
152
+ if batch_num % 1000 == 0:
153
+ print('\tValidation - Epoch %d | Batch %d | MSE Loss %6.2f' % (epoch, batch_num, loss.item()))
154
+ print('\tValidation - Epoch %d | Batch %d | MAE Loss %6.2f' % (epoch, batch_num, lossMAE.item()))
155
+
156
+ #print(y)
157
+
158
+ print('Validation - Epoch %d | MSE Loss %6.2f' % (epoch, sum(losses)/len(losses)))
159
+ print('Validation - Epoch %d | MAE Loss %6.2f' % (epoch, sum(losses2)/len(losses2)))
160
+ if sum(losses)/len(losses) < best_loss:
161
+ print("Best MAE Val loss so far. Saving model")
162
+ best_loss = sum(losses)/len(losses)
163
+ print( best_loss )
164
+
165
+ torch.save(model.state_dict(), save_name )
166
+
167
+
168
+ torch.save(model.state_dict(), save_name)
169
+
170
+ print( best_loss )
171
+
172
+ print("training done")
173
+ # inferece test with dummy samples from the val set, sanity check
174
+ print( "inferece test with dummy samples from the val set, sanity check")
175
+ model.eval()
176
+ output = model(x[:5].to(device))
177
+ print(output.size())
178
+ print(output)
improved-aesthetic-predictor/visulaize_100k_from_LAION400M.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import webdataset as wds
2
+ from PIL import Image
3
+ import io
4
+ import matplotlib.pyplot as plt
5
+ import os
6
+ import json
7
+
8
+ from warnings import filterwarnings
9
+
10
+
11
+ # os.environ["CUDA_VISIBLE_DEVICES"] = "0" # choose GPU if you are on a multi GPU server
12
+ import numpy as np
13
+ import torch
14
+ import pytorch_lightning as pl
15
+ import torch.nn as nn
16
+ from torchvision import datasets, transforms
17
+ import tqdm
18
+
19
+ from os.path import join
20
+ from datasets import load_dataset
21
+ import pandas as pd
22
+ from torch.utils.data import Dataset, DataLoader
23
+ import json
24
+
25
+ import clip
26
+ #import open_clip
27
+
28
+ from PIL import Image, ImageFile
29
+
30
+
31
+ # if you changed the MLP architecture during training, change it also here:
32
+
33
+ class MLP(pl.LightningModule):
34
+ def __init__(self, input_size, xcol='emb', ycol='avg_rating'):
35
+ super().__init__()
36
+ self.input_size = input_size
37
+ self.xcol = xcol
38
+ self.ycol = ycol
39
+ self.layers = nn.Sequential(
40
+ nn.Linear(self.input_size, 1024),
41
+ #nn.ReLU(),
42
+ nn.Dropout(0.2),
43
+ nn.Linear(1024, 128),
44
+ #nn.ReLU(),
45
+ nn.Dropout(0.2),
46
+ nn.Linear(128, 64),
47
+ #nn.ReLU(),
48
+ nn.Dropout(0.1),
49
+
50
+ nn.Linear(64, 16),
51
+ #nn.ReLU(),
52
+
53
+ nn.Linear(16, 1)
54
+ )
55
+
56
+ def forward(self, x):
57
+ return self.layers(x)
58
+
59
+ def training_step(self, batch, batch_idx):
60
+ x = batch[self.xcol]
61
+ y = batch[self.ycol].reshape(-1, 1)
62
+ x_hat = self.layers(x)
63
+ loss = F.mse_loss(x_hat, y)
64
+ return loss
65
+
66
+ def validation_step(self, batch, batch_idx):
67
+ x = batch[self.xcol]
68
+ y = batch[self.ycol].reshape(-1, 1)
69
+ x_hat = self.layers(x)
70
+ loss = F.mse_loss(x_hat, y)
71
+ return loss
72
+
73
+ def configure_optimizers(self):
74
+ optimizer = torch.optim.Adam(self.parameters(), lr=1e-3)
75
+ return optimizer
76
+
77
+ def normalized(a, axis=-1, order=2):
78
+ import numpy as np # pylint: disable=import-outside-toplevel
79
+
80
+ l2 = np.atleast_1d(np.linalg.norm(a, order, axis))
81
+ l2[l2 == 0] = 1
82
+ return a / np.expand_dims(l2, axis)
83
+
84
+
85
+ model = MLP(768) # CLIP embedding dim is 768 for CLIP ViT L 14
86
+
87
+ s = torch.load("ava+logos-l14-linearMSE.pth") # load the model you trained previously or the model available in this repo
88
+
89
+ model.load_state_dict(s)
90
+
91
+
92
+ model.to("cuda")
93
+ model.eval()
94
+
95
+
96
+
97
+
98
+
99
+ device = "cuda" if torch.cuda.is_available() else "cpu"
100
+ model2, preprocess = clip.load("ViT-L/14", device=device) #RN50x64
101
+
102
+
103
+
104
+ c=0
105
+ urls= []
106
+ predictions=[]
107
+
108
+ # this will run inference over 10 webdataset tar files from LAION 400M and sort them into 20 categories
109
+ # you can DL LAION 400M and convert it to wds tar files with img2dataset ( https://github.com/rom1504/img2dataset )
110
+
111
+
112
+ for j in range(10):
113
+ if j<10:
114
+ # change the path to the tar files accordingly
115
+ dataset = wds.WebDataset("pipe:aws s3 cp s3://s-datasets/laion400m/laion400m-dat-release/0000"+str(j)+".tar -") #"pipe:aws s3 cp s3://s-datasets/laion400m/laion400m-dat-release/00625.tar -")
116
+ else:
117
+ dataset = wds.WebDataset("pipe:aws s3 cp s3://s-datasets/laion400m/laion400m-dat-release/000"+str(j)+".tar -") #"pipe:aws s3 cp s3://s-datasets/laion400m/laion400m-dat-release/00625.tar -")
118
+
119
+
120
+ for i, d in enumerate(dataset):
121
+ print(c)
122
+
123
+ metadata= json.loads(d['json'])
124
+
125
+ pil_image = Image.open(io.BytesIO(d['jpg']))
126
+ c=c+1
127
+ try:
128
+ image = preprocess(pil_image).unsqueeze(0).to(device)
129
+
130
+ except:
131
+ continue
132
+
133
+ with torch.no_grad():
134
+ image_features = model2.encode_image(image)
135
+
136
+
137
+ im_emb_arr = normalized(image_features.cpu().detach().numpy() )
138
+
139
+ prediction = model(torch.from_numpy(im_emb_arr).to(device).type(torch.cuda.FloatTensor))
140
+ urls.append(metadata["url"])
141
+ predictions.append(prediction)
142
+
143
+
144
+ df = pd.DataFrame(list(zip(urls, predictions)),
145
+ columns =['filepath', 'prediction'])
146
+
147
+
148
+ buckets = [(i, i+1) for i in range(20)]
149
+
150
+
151
+ html= "<h1>Aesthetic subsets in LAION 100k samples</h1>"
152
+
153
+ i =0
154
+ for [a,b] in buckets:
155
+ a = a/2
156
+ b = b/2
157
+ total_part = df[( (df["prediction"] ) *1>= a) & ( (df["prediction"] ) *1 <= b)]
158
+ print(a,b)
159
+ print(len(total_part) )
160
+ count_part = len(total_part) / len(df) * 100
161
+ estimated =int ( len(total_part) )
162
+ part = total_part[:50]
163
+
164
+ html+=f"<h2>In bucket {a} - {b} there is {count_part:.2f}% samples:{estimated:.2f} </h2> <div>"
165
+ for filepath in part["filepath"]:
166
+ html+='<img src="'+filepath +'" height="200" />'
167
+
168
+
169
+ html+="</div>"
170
+ i+=1
171
+ print(i)
172
+ with open("./aesthetic_viz_laion_ava+logos_L14_100k-linearMSE.html", "w") as f:
173
+ f.write(html)
174
+
175
+
kaggle_evaluation/__init__.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ Competition helper module for the Drawing With LLMs Kaggle Competition.
3
+
4
+ Supports the `test` function for users to validate their Model, and internal functions
5
+ used by Kaggle's scoring system.
6
+ '''
7
+
8
+ import pathlib
9
+ import sys
10
+
11
+ # Provide additional import management since grpc_tools.protoc doesn't support relative imports
12
+ module_path = pathlib.Path(__file__).parent
13
+ gen_path = module_path / 'core' / 'generated'
14
+
15
+ if not (gen_path / 'kaggle_evaluation_pb2.py').exists():
16
+ msg = 'Missing required kaggle_evaluation proto / gRPC generated files.'
17
+ raise ImportError(msg)
18
+
19
+ sys.path.append(str(module_path))
20
+ sys.path.append(str(gen_path))
21
+
22
+ from .svg import test, _run_gateway, _run_inference_server
23
+ __all__ = ['test']
24
+
25
+ __version__ = '0.5.0'
kaggle_evaluation/core/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+
4
+
5
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
kaggle_evaluation/core/base_gateway.py ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ''' Lower level implementation details of the gateway.
2
+ Hosts should not need to review this file before writing their competition specific gateway.
3
+ '''
4
+
5
+ import enum
6
+ import json
7
+ import os
8
+ import pathlib
9
+ import re
10
+ import subprocess
11
+ import tempfile
12
+
13
+ from socket import gaierror
14
+ from typing import Any, List, Optional, Tuple, Union
15
+
16
+ import grpc
17
+ import numpy as np
18
+ import pandas as pd
19
+ import polars as pl
20
+
21
+ import kaggle_evaluation.core.relay
22
+
23
+
24
+ _FILE_SHARE_DIR = '/kaggle/shared/'
25
+ IS_RERUN = os.getenv('KAGGLE_IS_COMPETITION_RERUN') is not None
26
+
27
+
28
+ class GatewayRuntimeErrorType(enum.Enum):
29
+ ''' Allow-listed error types that Gateways can raise, which map to canned error messages to show users.'''
30
+ UNSPECIFIED = 0
31
+ SERVER_NEVER_STARTED = 1
32
+ SERVER_CONNECTION_FAILED = 2
33
+ SERVER_RAISED_EXCEPTION = 3
34
+ SERVER_MISSING_ENDPOINT = 4
35
+ # Default error type if an exception was raised that was not explicitly handled by the Gateway
36
+ GATEWAY_RAISED_EXCEPTION = 5
37
+ INVALID_SUBMISSION = 6
38
+
39
+
40
+ class GatewayRuntimeError(Exception):
41
+ ''' Gateways can raise this error to capture a user-visible error enum from above and host-visible error details.'''
42
+ def __init__(self, error_type: GatewayRuntimeErrorType, error_details: Optional[str]=None):
43
+ self.error_type = error_type
44
+ self.error_details = error_details
45
+
46
+
47
+ class BaseGateway():
48
+ def __init__(self, target_column_name: Optional[str]=None):
49
+ self.client = kaggle_evaluation.core.relay.Client('inference_server' if IS_RERUN else 'localhost')
50
+ self.server = None # The gateway can have a server but it isn't typically necessary.
51
+ self.target_column_name = target_column_name # Only used if the predictions are made as a primitive type (int, bool, etc) rather than a dataframe.
52
+
53
+ def validate_prediction_batch(
54
+ self,
55
+ prediction_batch: Any,
56
+ row_ids: Union[pl.DataFrame, pl.Series, pd.DataFrame, pd.Series]
57
+ ):
58
+ ''' If competitors can submit fewer rows than expected they can save all predictions for the last batch and
59
+ bypass the benefits of the Kaggle evaluation service. This attack was seen in a real competition with the older time series API:
60
+ https://www.kaggle.com/competitions/riiid-test-answer-prediction/discussion/196066
61
+ It's critically important that this check be run every time predict() is called.
62
+
63
+ If your predictions may take a variable number of rows and you need to write a custom version of this check,
64
+ you still must specify a minimum row count greater than zero per prediction batch.
65
+ '''
66
+ if prediction_batch is None:
67
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, 'No prediction received')
68
+ num_received_rows = None
69
+ # Special handling for numpy ints only as numpy floats are python floats, but numpy ints aren't python ints
70
+ for primitive_type in [int, float, str, bool, np.int_]:
71
+ if isinstance(prediction_batch, primitive_type):
72
+ # Types that only support one predictions per batch don't need to be validated.
73
+ # Basic types are valid for prediction, but either don't have a length (int) or the length isn't relevant for
74
+ # purposes of this check (str).
75
+ num_received_rows = 1
76
+ if num_received_rows is None:
77
+ if type(prediction_batch) not in [pl.DataFrame, pl.Series, pd.DataFrame, pd.Series]:
78
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, f'Invalid prediction data type, received: {type(prediction_batch)}')
79
+ num_received_rows = len(prediction_batch)
80
+ if type(row_ids) not in [pl.DataFrame, pl.Series, pd.DataFrame, pd.Series]:
81
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.GATEWAY_RAISED_EXCEPTION, f'Invalid row ID type {type(row_ids)}; expected Polars DataFrame or similar')
82
+ num_expected_rows = len(row_ids)
83
+ if len(row_ids) == 0:
84
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.GATEWAY_RAISED_EXCEPTION, 'Missing row IDs for batch')
85
+ if num_received_rows != num_expected_rows:
86
+ raise GatewayRuntimeError(
87
+ GatewayRuntimeErrorType.INVALID_SUBMISSION,
88
+ f'Invalid predictions: expected {num_expected_rows} rows but received {num_received_rows}'
89
+ )
90
+
91
+ def _standardize_and_validate_paths(
92
+ self,
93
+ input_paths: List[Union[str, pathlib.Path]]
94
+ ) -> List[pathlib.Path]:
95
+ # Accept a list of str or pathlib.Path, but standardize on list of str
96
+ for path in input_paths:
97
+ if os.pardir in str(path):
98
+ raise ValueError(f'Send files path contains {os.pardir}: {path}')
99
+ if str(path) != str(os.path.normpath(path)):
100
+ # Raise an error rather than sending users unexpectedly altered paths
101
+ raise ValueError(f'Send files path {path} must be normalized. See `os.path.normpath`')
102
+ if type(path) not in (pathlib.Path, str):
103
+ raise ValueError('All paths must be of type str or pathlib.Path')
104
+ if not os.path.exists(path):
105
+ raise ValueError(f'Input path {path} does not exist')
106
+
107
+ input_paths = [os.path.abspath(path) for path in input_paths]
108
+ if len(set(input_paths)) != len(input_paths):
109
+ raise ValueError('Duplicate input paths found')
110
+
111
+ if not self.file_share_dir.endswith(os.path.sep):
112
+ # Ensure output dir is valid for later use
113
+ output_dir = self.file_share_dir + os.path.sep
114
+
115
+ if not os.path.exists(self.file_share_dir) or not os.path.isdir(self.file_share_dir):
116
+ raise ValueError(f'Invalid output directory {self.file_share_dir}')
117
+ # Can't use os.path.join for output_dir + path: os.path.join won't prepend to an abspath
118
+ output_paths = [output_dir + path for path in input_paths]
119
+ return input_paths, output_paths
120
+
121
+ def share_files(
122
+ self,
123
+ input_paths: List[Union[str, pathlib.Path]],
124
+ ) -> List[str]:
125
+ ''' Makes files and/or directories available to the user's inference_server. They will be mirrored under the
126
+ self.file_share_dir directory, using the full absolute path. An input like:
127
+ /kaggle/input/mycomp/test.csv
128
+ Would be written to:
129
+ /kaggle/shared/kaggle/input/mycomp/test.csv
130
+
131
+ Args:
132
+ input_paths: List of paths to files and/or directories that should be shared.
133
+
134
+ Returns:
135
+ The output paths that were shared.
136
+
137
+ Raises:
138
+ ValueError if any invalid paths are passed.
139
+ '''
140
+ input_paths, output_paths = self._standardize_and_validate_paths(input_paths)
141
+ for in_path, out_path in zip(input_paths, output_paths):
142
+ os.makedirs(os.path.dirname(out_path), exist_ok=True)
143
+
144
+ # This makes the files available to the InferenceServer as read-only. Only the Gateway can mount files.
145
+ # mount will only work in live kaggle evaluation rerun sessions. Otherwise use a symlink.
146
+ if IS_RERUN:
147
+ if not os.path.isdir(out_path):
148
+ pathlib.Path(out_path).touch()
149
+ subprocess.run(f'mount --bind {in_path} {out_path}', shell=True, check=True)
150
+ else:
151
+ subprocess.run(f'ln -s {in_path} {out_path}', shell=True, check=True)
152
+
153
+ return output_paths
154
+
155
+ def write_submission(self, predictions, row_ids: List[Union[pl.Series, pl.DataFrame, pd.Series, pd.DataFrame]]) -> pathlib.Path:
156
+ ''' Export the predictions to a submission file.'''
157
+ if isinstance(predictions, list):
158
+ if isinstance(predictions[0], pd.DataFrame):
159
+ predictions = pd.concat(predictions, ignore_index=True)
160
+ elif isinstance(predictions[0], pl.DataFrame):
161
+ try:
162
+ predictions = pl.concat(predictions, how='vertical_relaxed')
163
+ except pl.exceptions.SchemaError:
164
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, 'Inconsistent prediction types')
165
+ except pl.exceptions.ComputeError:
166
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, 'Inconsistent prediction column counts')
167
+ elif isinstance(predictions[0], pl.Series):
168
+ try:
169
+ predictions = pl.concat(predictions, how='vertical')
170
+ except pl.exceptions.SchemaError:
171
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, 'Inconsistent prediction types')
172
+ except pl.exceptions.ComputeError:
173
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, 'Inconsistent prediction column counts')
174
+
175
+ if type(row_ids[0]) in [pl.Series, pl.DataFrame]:
176
+ row_ids = pl.concat(row_ids)
177
+ elif type(row_ids[0]) in [pd.Series, pd.DataFrame]:
178
+ row_ids = pd.concat(row_ids).reset_index(drop=True)
179
+ else:
180
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.GATEWAY_RAISED_EXCEPTION, f'Invalid row ID datatype {type(row_ids[0])}. Expected Polars series or dataframe.')
181
+ if self.target_column_name is None:
182
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.GATEWAY_RAISED_EXCEPTION, '`target_column_name` must be set in order to use scalar value predictions.')
183
+ predictions = pl.DataFrame(data={row_ids.columns[0]: row_ids, self.target_column_name: predictions})
184
+
185
+ submission_path = pathlib.Path('/kaggle/working/submission.csv')
186
+ if not IS_RERUN:
187
+ with tempfile.NamedTemporaryFile(prefix='kaggle-evaluation-submission-', suffix='.csv', delete=False, mode='w+') as f:
188
+ submission_path = pathlib.Path(f.name)
189
+
190
+ if isinstance(predictions, pd.DataFrame):
191
+ predictions.to_csv(submission_path, index=False)
192
+ elif isinstance(predictions, pl.DataFrame):
193
+ pl.DataFrame(predictions).write_csv(submission_path)
194
+ else:
195
+ raise ValueError(f"Unsupported predictions type {type(predictions)}; can't write submission file")
196
+
197
+ return submission_path
198
+
199
+ def write_result(self, error: Optional[GatewayRuntimeError]=None):
200
+ ''' Export a result.json containing error details if applicable.'''
201
+ result = { 'Succeeded': error is None }
202
+
203
+ if error is not None:
204
+ result['ErrorType'] = error.error_type.value
205
+ result['ErrorName'] = error.error_type.name
206
+ # Max error detail length is 8000
207
+ result['ErrorDetails'] = str(error.error_details[:8000]) if error.error_details else None
208
+
209
+ with open('result.json', 'w') as f_open:
210
+ json.dump(result, f_open)
211
+
212
+ def handle_server_error(self, exception: Exception, endpoint: str):
213
+ ''' Determine how to handle an exception raised when calling the inference server. Typically just format the
214
+ error into a GatewayRuntimeError and raise.
215
+ '''
216
+ exception_str = str(exception)
217
+ if isinstance(exception, gaierror) or (isinstance(exception, RuntimeError) and 'Failed to connect to server after waiting' in exception_str):
218
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.SERVER_NEVER_STARTED) from None
219
+ if f'No listener for {endpoint} was registered' in exception_str:
220
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.SERVER_MISSING_ENDPOINT, f'Server did not register a listener for {endpoint}') from None
221
+ if 'Exception calling application' in exception_str:
222
+ # Extract just the exception message raised by the inference server
223
+ message_match = re.search('"Exception calling application: (.*)"', exception_str, re.IGNORECASE)
224
+ message = message_match.group(1) if message_match else exception_str
225
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.SERVER_RAISED_EXCEPTION, message) from None
226
+ if isinstance(exception, grpc._channel._InactiveRpcError):
227
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.SERVER_CONNECTION_FAILED, exception_str) from None
228
+
229
+ raise exception
kaggle_evaluation/core/generated/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+
4
+
5
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
kaggle_evaluation/core/generated/kaggle_evaluation_pb2.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # source: kaggle_evaluation.proto
4
+ # Protobuf Python Version: 4.25.1
5
+ """Generated protocol buffer code."""
6
+ from google.protobuf import descriptor as _descriptor
7
+ from google.protobuf import descriptor_pool as _descriptor_pool
8
+ from google.protobuf import symbol_database as _symbol_database
9
+ from google.protobuf.internal import builder as _builder
10
+ # @@protoc_insertion_point(imports)
11
+
12
+ _sym_db = _symbol_database.Default()
13
+
14
+
15
+
16
+
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17kaggle_evaluation.proto\x12\x18kaggle_evaluation_client\"\xf9\x01\n\x17KaggleEvaluationRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12/\n\x04\x61rgs\x18\x02 \x03(\x0b\x32!.kaggle_evaluation_client.Payload\x12M\n\x06kwargs\x18\x03 \x03(\x0b\x32=.kaggle_evaluation_client.KaggleEvaluationRequest.KwargsEntry\x1aP\n\x0bKwargsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.kaggle_evaluation_client.Payload:\x02\x38\x01\"N\n\x18KaggleEvaluationResponse\x12\x32\n\x07payload\x18\x01 \x01(\x0b\x32!.kaggle_evaluation_client.Payload\"\x8d\x04\n\x07Payload\x12\x13\n\tstr_value\x18\x01 \x01(\tH\x00\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x13\n\tint_value\x18\x03 \x01(\x12H\x00\x12\x15\n\x0b\x66loat_value\x18\x04 \x01(\x02H\x00\x12\x14\n\nnone_value\x18\x05 \x01(\x08H\x00\x12;\n\nlist_value\x18\x06 \x01(\x0b\x32%.kaggle_evaluation_client.PayloadListH\x00\x12<\n\x0btuple_value\x18\x07 \x01(\x0b\x32%.kaggle_evaluation_client.PayloadListH\x00\x12:\n\ndict_value\x18\x08 \x01(\x0b\x32$.kaggle_evaluation_client.PayloadMapH\x00\x12 \n\x16pandas_dataframe_value\x18\t \x01(\x0cH\x00\x12 \n\x16polars_dataframe_value\x18\n \x01(\x0cH\x00\x12\x1d\n\x13pandas_series_value\x18\x0b \x01(\x0cH\x00\x12\x1d\n\x13polars_series_value\x18\x0c \x01(\x0cH\x00\x12\x1b\n\x11numpy_array_value\x18\r \x01(\x0cH\x00\x12\x1c\n\x12numpy_scalar_value\x18\x0e \x01(\x0cH\x00\x12\x18\n\x0e\x62ytes_io_value\x18\x0f \x01(\x0cH\x00\x42\x07\n\x05value\"B\n\x0bPayloadList\x12\x33\n\x08payloads\x18\x01 \x03(\x0b\x32!.kaggle_evaluation_client.Payload\"\xad\x01\n\nPayloadMap\x12I\n\x0bpayload_map\x18\x01 \x03(\x0b\x32\x34.kaggle_evaluation_client.PayloadMap.PayloadMapEntry\x1aT\n\x0fPayloadMapEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x30\n\x05value\x18\x02 \x01(\x0b\x32!.kaggle_evaluation_client.Payload:\x02\x38\x01\x32\x8a\x01\n\x17KaggleEvaluationService\x12o\n\x04Send\x12\x31.kaggle_evaluation_client.KaggleEvaluationRequest\x1a\x32.kaggle_evaluation_client.KaggleEvaluationResponse\"\x00\x62\x06proto3')
18
+
19
+ _globals = globals()
20
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
21
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'kaggle_evaluation_pb2', _globals)
22
+ if _descriptor._USE_C_DESCRIPTORS == False:
23
+ DESCRIPTOR._options = None
24
+ _globals['_KAGGLEEVALUATIONREQUEST_KWARGSENTRY']._options = None
25
+ _globals['_KAGGLEEVALUATIONREQUEST_KWARGSENTRY']._serialized_options = b'8\001'
26
+ _globals['_PAYLOADMAP_PAYLOADMAPENTRY']._options = None
27
+ _globals['_PAYLOADMAP_PAYLOADMAPENTRY']._serialized_options = b'8\001'
28
+ _globals['_KAGGLEEVALUATIONREQUEST']._serialized_start=54
29
+ _globals['_KAGGLEEVALUATIONREQUEST']._serialized_end=303
30
+ _globals['_KAGGLEEVALUATIONREQUEST_KWARGSENTRY']._serialized_start=223
31
+ _globals['_KAGGLEEVALUATIONREQUEST_KWARGSENTRY']._serialized_end=303
32
+ _globals['_KAGGLEEVALUATIONRESPONSE']._serialized_start=305
33
+ _globals['_KAGGLEEVALUATIONRESPONSE']._serialized_end=383
34
+ _globals['_PAYLOAD']._serialized_start=386
35
+ _globals['_PAYLOAD']._serialized_end=911
36
+ _globals['_PAYLOADLIST']._serialized_start=913
37
+ _globals['_PAYLOADLIST']._serialized_end=979
38
+ _globals['_PAYLOADMAP']._serialized_start=982
39
+ _globals['_PAYLOADMAP']._serialized_end=1155
40
+ _globals['_PAYLOADMAP_PAYLOADMAPENTRY']._serialized_start=1071
41
+ _globals['_PAYLOADMAP_PAYLOADMAPENTRY']._serialized_end=1155
42
+ _globals['_KAGGLEEVALUATIONSERVICE']._serialized_start=1158
43
+ _globals['_KAGGLEEVALUATIONSERVICE']._serialized_end=1296
44
+ # @@protoc_insertion_point(module_scope)
kaggle_evaluation/core/generated/kaggle_evaluation_pb2_grpc.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
2
+ """Client and server classes corresponding to protobuf-defined services."""
3
+ import grpc
4
+
5
+ import kaggle_evaluation_pb2 as kaggle__evaluation__pb2
6
+
7
+
8
+ class KaggleEvaluationServiceStub(object):
9
+ """Missing associated documentation comment in .proto file."""
10
+
11
+ def __init__(self, channel):
12
+ """Constructor.
13
+
14
+ Args:
15
+ channel: A grpc.Channel.
16
+ """
17
+ self.Send = channel.unary_unary(
18
+ '/kaggle_evaluation_client.KaggleEvaluationService/Send',
19
+ request_serializer=kaggle__evaluation__pb2.KaggleEvaluationRequest.SerializeToString,
20
+ response_deserializer=kaggle__evaluation__pb2.KaggleEvaluationResponse.FromString,
21
+ )
22
+
23
+
24
+ class KaggleEvaluationServiceServicer(object):
25
+ """Missing associated documentation comment in .proto file."""
26
+
27
+ def Send(self, request, context):
28
+ """Missing associated documentation comment in .proto file."""
29
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
30
+ context.set_details('Method not implemented!')
31
+ raise NotImplementedError('Method not implemented!')
32
+
33
+
34
+ def add_KaggleEvaluationServiceServicer_to_server(servicer, server):
35
+ rpc_method_handlers = {
36
+ 'Send': grpc.unary_unary_rpc_method_handler(
37
+ servicer.Send,
38
+ request_deserializer=kaggle__evaluation__pb2.KaggleEvaluationRequest.FromString,
39
+ response_serializer=kaggle__evaluation__pb2.KaggleEvaluationResponse.SerializeToString,
40
+ ),
41
+ }
42
+ generic_handler = grpc.method_handlers_generic_handler(
43
+ 'kaggle_evaluation_client.KaggleEvaluationService', rpc_method_handlers)
44
+ server.add_generic_rpc_handlers((generic_handler,))
45
+
46
+
47
+ # This class is part of an EXPERIMENTAL API.
48
+ class KaggleEvaluationService(object):
49
+ """Missing associated documentation comment in .proto file."""
50
+
51
+ @staticmethod
52
+ def Send(request,
53
+ target,
54
+ options=(),
55
+ channel_credentials=None,
56
+ call_credentials=None,
57
+ insecure=False,
58
+ compression=None,
59
+ wait_for_ready=None,
60
+ timeout=None,
61
+ metadata=None):
62
+ return grpc.experimental.unary_unary(request, target, '/kaggle_evaluation_client.KaggleEvaluationService/Send',
63
+ kaggle__evaluation__pb2.KaggleEvaluationRequest.SerializeToString,
64
+ kaggle__evaluation__pb2.KaggleEvaluationResponse.FromString,
65
+ options, channel_credentials,
66
+ insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
kaggle_evaluation/core/kaggle_evaluation.proto ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Defines the proto service for KaggleEvaluation communication, aiming to provide native
2
+ // support for passing a variety of python primitives + common data science
3
+ // objects, and nested objects thereof.
4
+
5
+ syntax = "proto3";
6
+
7
+ package kaggle_evaluation_client;
8
+
9
+ service KaggleEvaluationService {
10
+ rpc Send(KaggleEvaluationRequest) returns (KaggleEvaluationResponse) {};
11
+ }
12
+
13
+ message KaggleEvaluationRequest {
14
+ string name = 1;
15
+ // Support generic python method calls using standard args / kwargs format.
16
+ repeated Payload args = 2;
17
+ map<string, Payload> kwargs = 3;
18
+ }
19
+
20
+ message KaggleEvaluationResponse {
21
+ Payload payload = 1;
22
+ }
23
+
24
+ // Core object representing a python value.
25
+ message Payload {
26
+ oneof value {
27
+ // Primitives
28
+ string str_value = 1;
29
+ bool bool_value = 2;
30
+ sint64 int_value = 3;
31
+ float float_value = 4;
32
+ // Value is ignored, being set at all means `None`
33
+ bool none_value = 5;
34
+
35
+ // Iterables for nested types
36
+ PayloadList list_value = 6;
37
+ PayloadList tuple_value = 7;
38
+ // Only supports dict with keys of type str and values that are serializable
39
+ // to Payload as well.
40
+ PayloadMap dict_value = 8;
41
+
42
+ // Allowlisted special types
43
+ // pandas.DataFrame
44
+ bytes pandas_dataframe_value = 9;
45
+ // polars.DataFrame
46
+ bytes polars_dataframe_value = 10;
47
+ // pandas.Series
48
+ bytes pandas_series_value = 11;
49
+ // polars.Series
50
+ bytes polars_series_value = 12;
51
+ // numpy.ndarray
52
+ bytes numpy_array_value = 13;
53
+ // numpy.scalar. Distinct from numpy.ndarray to avoid issues with dimensionless numpy arrays
54
+ bytes numpy_scalar_value = 14;
55
+ // io.BytesIO
56
+ bytes bytes_io_value = 15;
57
+ }
58
+ }
59
+
60
+ message PayloadList {
61
+ repeated Payload payloads = 1;
62
+ }
63
+
64
+ message PayloadMap {
65
+ map<string, Payload> payload_map = 1;
66
+ }
kaggle_evaluation/core/relay.py ADDED
@@ -0,0 +1,343 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''
2
+ Core implementation of the client module, implementing generic communication
3
+ patterns with Python in / Python out supporting many (nested) primitives +
4
+ special data science types like DataFrames or np.ndarrays, with gRPC + protobuf
5
+ as a backing implementation.
6
+ '''
7
+
8
+ import grpc
9
+ import io
10
+ import json
11
+ import socket
12
+ import time
13
+
14
+ from concurrent import futures
15
+ from typing import Callable, List, Tuple
16
+
17
+ import numpy as np
18
+ import pandas as pd
19
+ import polars as pl
20
+ import pyarrow
21
+
22
+ import kaggle_evaluation.core.generated.kaggle_evaluation_pb2 as kaggle_evaluation_proto
23
+ import kaggle_evaluation.core.generated.kaggle_evaluation_pb2_grpc as kaggle_evaluation_grpc
24
+
25
+
26
+ _SERVICE_CONFIG = {
27
+ # Service config proto: https://github.com/grpc/grpc-proto/blob/ec886024c2f7b7f597ba89d5b7d60c3f94627b17/grpc/service_config/service_config.proto#L377
28
+ 'methodConfig': [
29
+ {
30
+ 'name': [{}], # Applies to all methods
31
+ # See retry policy docs: https://grpc.io/docs/guides/retry/
32
+ 'retryPolicy': {
33
+ 'maxAttempts': 5,
34
+ 'initialBackoff': '0.1s',
35
+ 'maxBackoff': '1s',
36
+ 'backoffMultiplier': 1, # Ensure relatively rapid feedback in the event of a crash
37
+ 'retryableStatusCodes': ['UNAVAILABLE'],
38
+ },
39
+ }
40
+ ]
41
+ }
42
+ _GRPC_PORT = 50051
43
+ _GRPC_CHANNEL_OPTIONS = [
44
+ # -1 for unlimited message send/receive size
45
+ # https://github.com/grpc/grpc/blob/v1.64.x/include/grpc/impl/channel_arg_names.h#L39
46
+ ('grpc.max_send_message_length', -1),
47
+ ('grpc.max_receive_message_length', -1),
48
+ # https://github.com/grpc/grpc/blob/master/doc/keepalive.md
49
+ ('grpc.keepalive_time_ms', 60_000), # Time between heartbeat pings
50
+ ('grpc.keepalive_timeout_ms', 5_000), # Time allowed to respond to pings
51
+ ('grpc.http2.max_pings_without_data', 0), # Remove another cap on pings
52
+ ('grpc.keepalive_permit_without_calls', 1), # Allow heartbeat pings at any time
53
+ ('grpc.http2.min_ping_interval_without_data_ms', 1_000),
54
+ ('grpc.service_config', json.dumps(_SERVICE_CONFIG)),
55
+ ]
56
+
57
+
58
+ DEFAULT_DEADLINE_SECONDS = 60 * 60
59
+ _RETRY_SLEEP_SECONDS = 1
60
+ # Enforce a relatively strict server startup time so users can get feedback quickly if they're not
61
+ # configuring KaggleEvaluation correctly. We really don't want notebooks timing out after nine hours
62
+ # somebody forgot to start their inference_server. Slow steps like loading models
63
+ # can happen during the first inference call if necessary.
64
+ STARTUP_LIMIT_SECONDS = 60 * 15
65
+
66
+ ### Utils shared by client and server for data transfer
67
+
68
+ # pl.Enum is currently unstable, but we should eventually consider supporting it.
69
+ # https://docs.pola.rs/api/python/stable/reference/api/polars.datatypes.Enum.html#polars.datatypes.Enum
70
+ _POLARS_TYPE_DENYLIST = set([pl.Enum, pl.Object, pl.Unknown])
71
+
72
+ def _serialize(data) -> kaggle_evaluation_proto.Payload:
73
+ '''Maps input data of one of several allow-listed types to a protobuf message to be sent over gRPC.
74
+
75
+ Args:
76
+ data: The input data to be mapped. Any of the types listed below are accepted.
77
+
78
+ Returns:
79
+ The Payload protobuf message.
80
+
81
+ Raises:
82
+ TypeError if data is of an unsupported type.
83
+ '''
84
+ # Python primitives and Numpy scalars
85
+ if isinstance(data, np.generic):
86
+ # Numpy functions that return a single number return numpy scalars instead of python primitives.
87
+ # In some cases this difference matters: https://numpy.org/devdocs/release/2.0.0-notes.html#representation-of-numpy-scalars-changed
88
+ # Ex: np.mean(1,2) yields np.float64(1.5) instead of 1.5.
89
+ # Check for numpy scalars first since most of them also inherit from python primitives.
90
+ # For example, `np.float64(1.5)` is an instance of `float` among many other things.
91
+ # https://numpy.org/doc/stable/reference/arrays.scalars.html
92
+ assert data.shape == () # Additional validation that the np.generic type remains solely for scalars
93
+ assert isinstance(data, np.number) or isinstance(data, np.bool_) # No support for bytes, strings, objects, etc
94
+ buffer = io.BytesIO()
95
+ np.save(buffer, data, allow_pickle=False)
96
+ return kaggle_evaluation_proto.Payload(numpy_scalar_value=buffer.getvalue())
97
+ elif isinstance(data, str):
98
+ return kaggle_evaluation_proto.Payload(str_value=data)
99
+ elif isinstance(data, bool): # bool is a subclass of int, so check that first
100
+ return kaggle_evaluation_proto.Payload(bool_value=data)
101
+ elif isinstance(data, int):
102
+ return kaggle_evaluation_proto.Payload(int_value=data)
103
+ elif isinstance(data, float):
104
+ return kaggle_evaluation_proto.Payload(float_value=data)
105
+ elif data is None:
106
+ return kaggle_evaluation_proto.Payload(none_value=True)
107
+ # Iterables for nested types
108
+ if isinstance(data, list):
109
+ return kaggle_evaluation_proto.Payload(list_value=kaggle_evaluation_proto.PayloadList(payloads=map(_serialize, data)))
110
+ elif isinstance(data, tuple):
111
+ return kaggle_evaluation_proto.Payload(tuple_value=kaggle_evaluation_proto.PayloadList(payloads=map(_serialize, data)))
112
+ elif isinstance(data, dict):
113
+ serialized_dict = {}
114
+ for key, value in data.items():
115
+ if not isinstance(key, str):
116
+ raise TypeError(f'KaggleEvaluation only supports dicts with keys of type str, found {type(key)}.')
117
+ serialized_dict[key] = _serialize(value)
118
+ return kaggle_evaluation_proto.Payload(dict_value=kaggle_evaluation_proto.PayloadMap(payload_map=serialized_dict))
119
+ # Allowlisted special types
120
+ if isinstance(data, pd.DataFrame):
121
+ buffer = io.BytesIO()
122
+ data.to_parquet(buffer, index=False, compression='lz4')
123
+ return kaggle_evaluation_proto.Payload(pandas_dataframe_value=buffer.getvalue())
124
+ elif isinstance(data, pl.DataFrame):
125
+ data_types = set(i.base_type() for i in data.dtypes)
126
+ banned_types = _POLARS_TYPE_DENYLIST.intersection(data_types)
127
+ if len(banned_types) > 0:
128
+ raise TypeError(f'Unsupported Polars data type(s): {banned_types}')
129
+
130
+ table = data.to_arrow()
131
+ buffer = io.BytesIO()
132
+ with pyarrow.ipc.new_stream(buffer, table.schema, options=pyarrow.ipc.IpcWriteOptions(compression='lz4')) as writer:
133
+ writer.write_table(table)
134
+ return kaggle_evaluation_proto.Payload(polars_dataframe_value=buffer.getvalue())
135
+ elif isinstance(data, pd.Series):
136
+ buffer = io.BytesIO()
137
+ # Can't serialize a pd.Series directly to parquet, must use intermediate DataFrame
138
+ pd.DataFrame(data).to_parquet(buffer, index=False, compression='lz4')
139
+ return kaggle_evaluation_proto.Payload(pandas_series_value=buffer.getvalue())
140
+ elif isinstance(data, pl.Series):
141
+ buffer = io.BytesIO()
142
+ # Can't serialize a pl.Series directly to parquet, must use intermediate DataFrame
143
+ pl.DataFrame(data).write_parquet(buffer, compression='lz4', statistics=False)
144
+ return kaggle_evaluation_proto.Payload(polars_series_value=buffer.getvalue())
145
+ elif isinstance(data, np.ndarray):
146
+ buffer = io.BytesIO()
147
+ np.save(buffer, data, allow_pickle=False)
148
+ return kaggle_evaluation_proto.Payload(numpy_array_value=buffer.getvalue())
149
+ elif isinstance(data, io.BytesIO):
150
+ return kaggle_evaluation_proto.Payload(bytes_io_value=data.getvalue())
151
+
152
+ raise TypeError(f'Type {type(data)} not supported for KaggleEvaluation.')
153
+
154
+
155
+ def _deserialize(payload: kaggle_evaluation_proto.Payload):
156
+ '''Maps a Payload protobuf message to a value of whichever type was set on the message.
157
+
158
+ Args:
159
+ payload: The message to be mapped.
160
+
161
+ Returns:
162
+ A value of one of several allow-listed types.
163
+
164
+ Raises:
165
+ TypeError if an unexpected value data type is found.
166
+ '''
167
+ # Primitives
168
+ if payload.WhichOneof('value') == 'str_value':
169
+ return payload.str_value
170
+ elif payload.WhichOneof('value') == 'bool_value':
171
+ return payload.bool_value
172
+ elif payload.WhichOneof('value') == 'int_value':
173
+ return payload.int_value
174
+ elif payload.WhichOneof('value') == 'float_value':
175
+ return payload.float_value
176
+ elif payload.WhichOneof('value') == 'none_value':
177
+ return None
178
+ # Iterables for nested types
179
+ elif payload.WhichOneof('value') == 'list_value':
180
+ return list(map(_deserialize, payload.list_value.payloads))
181
+ elif payload.WhichOneof('value') == 'tuple_value':
182
+ return tuple(map(_deserialize, payload.tuple_value.payloads))
183
+ elif payload.WhichOneof('value') == 'dict_value':
184
+ return {key: _deserialize(value) for key, value in payload.dict_value.payload_map.items()}
185
+ # Allowlisted special types
186
+ elif payload.WhichOneof('value') == 'pandas_dataframe_value':
187
+ return pd.read_parquet(io.BytesIO(payload.pandas_dataframe_value))
188
+ elif payload.WhichOneof('value') == 'polars_dataframe_value':
189
+ with pyarrow.ipc.open_stream(payload.polars_dataframe_value) as reader:
190
+ table = reader.read_all()
191
+ return pl.from_arrow(table)
192
+ elif payload.WhichOneof('value') == 'pandas_series_value':
193
+ # Pandas will still read a single column csv as a DataFrame.
194
+ df = pd.read_parquet(io.BytesIO(payload.pandas_series_value))
195
+ return pd.Series(df[df.columns[0]])
196
+ elif payload.WhichOneof('value') == 'polars_series_value':
197
+ return pl.Series(pl.read_parquet(io.BytesIO(payload.polars_series_value)))
198
+ elif payload.WhichOneof('value') == 'numpy_array_value':
199
+ return np.load(io.BytesIO(payload.numpy_array_value), allow_pickle=False)
200
+ elif payload.WhichOneof('value') == 'numpy_scalar_value':
201
+ data = np.load(io.BytesIO(payload.numpy_scalar_value), allow_pickle=False)
202
+ # As of Numpy 2.0.2, np.load for a numpy scalar yields a dimensionless array instead of a scalar
203
+ data = data.dtype.type(data) # Restore the expected numpy scalar type.
204
+ assert data.shape == () # Additional validation that the np.generic type remains solely for scalars
205
+ assert isinstance(data, np.number) or isinstance(data, np.bool_) # No support for bytes, strings, objects, etc
206
+ return data
207
+ elif payload.WhichOneof('value') == 'bytes_io_value':
208
+ return io.BytesIO(payload.bytes_io_value)
209
+
210
+ raise TypeError(f'Found unknown Payload case {payload.WhichOneof("value")}')
211
+
212
+ ### Client code
213
+
214
+ class Client():
215
+ '''
216
+ Class which allows callers to make KaggleEvaluation requests.
217
+ '''
218
+ def __init__(self, channel_address: str='localhost'):
219
+ self.channel_address = channel_address
220
+ self.channel = grpc.insecure_channel(f'{channel_address}:{_GRPC_PORT}', options=_GRPC_CHANNEL_OPTIONS)
221
+ self._made_first_connection = False
222
+ self.endpoint_deadline_seconds = DEFAULT_DEADLINE_SECONDS
223
+ self.stub = kaggle_evaluation_grpc.KaggleEvaluationServiceStub(self.channel)
224
+
225
+ def _send_with_deadline(self, request):
226
+ ''' Sends a message to the server while also:
227
+ - Throwing an error as soon as the inference_server container has been shut down.
228
+ - Setting a deadline of STARTUP_LIMIT_SECONDS for the inference_server to startup.
229
+ '''
230
+ if self._made_first_connection:
231
+ return self.stub.Send(request, wait_for_ready=False, timeout=self.endpoint_deadline_seconds)
232
+
233
+ first_call_time = time.time()
234
+ # Allow time for the server to start as long as its container is running
235
+ while time.time() - first_call_time < STARTUP_LIMIT_SECONDS:
236
+ try:
237
+ response = self.stub.Send(request, wait_for_ready=False)
238
+ self._made_first_connection = True
239
+ break
240
+ except grpc._channel._InactiveRpcError as err:
241
+ if 'StatusCode.UNAVAILABLE' not in str(err):
242
+ raise err
243
+ # Confirm the inference_server container is still alive & it's worth waiting on the server.
244
+ # If the inference_server container is no longer running this will throw a socket.gaierror.
245
+ socket.gethostbyname(self.channel_address)
246
+ time.sleep(_RETRY_SLEEP_SECONDS)
247
+
248
+ if not self._made_first_connection:
249
+ raise RuntimeError(f'Failed to connect to server after waiting {STARTUP_LIMIT_SECONDS} seconds')
250
+ return response
251
+
252
+ def serialize_request(self, name: str, *args, **kwargs) -> kaggle_evaluation_proto.KaggleEvaluationRequest:
253
+ ''' Serialize a single request. Exists as a separate function from `send`
254
+ to enable gateway concurrency for some competitions.
255
+ '''
256
+ already_serialized = (len(args) == 1) and isinstance(args[0], kaggle_evaluation_proto.KaggleEvaluationRequest)
257
+ if already_serialized:
258
+ return args[0] # args is a tuple of length 1 containing the request
259
+ return kaggle_evaluation_proto.KaggleEvaluationRequest(
260
+ name=name,
261
+ args=map(_serialize, args),
262
+ kwargs={key: _serialize(value) for key, value in kwargs.items()}
263
+ )
264
+
265
+ def send(self, name: str, *args, **kwargs):
266
+ '''Sends a single KaggleEvaluation request.
267
+
268
+ Args:
269
+ name: The endpoint name for the request.
270
+ *args: Variable-length/type arguments to be supplied on the request.
271
+ **kwargs: Key-value arguments to be supplied on the request.
272
+
273
+ Returns:
274
+ The response, which is of one of several allow-listed data types.
275
+ '''
276
+ request = self.serialize_request(name, *args, **kwargs)
277
+ response = self._send_with_deadline(request)
278
+ return _deserialize(response.payload)
279
+
280
+ def close(self):
281
+ self.channel.close()
282
+
283
+
284
+ ### Server code
285
+
286
+ class KaggleEvaluationServiceServicer(kaggle_evaluation_grpc.KaggleEvaluationServiceServicer):
287
+ '''
288
+ Class which allows serving responses to KaggleEvaluation requests. The inference_server will run this service to listen for and respond
289
+ to requests from the Gateway. The Gateway may also listen for requests from the inference_server in some cases.
290
+ '''
291
+ def __init__(self, listeners: List[callable]):
292
+ self.listeners_map = dict((func.__name__, func) for func in listeners)
293
+
294
+ # pylint: disable=unused-argument
295
+ def Send(self, request: kaggle_evaluation_proto.KaggleEvaluationRequest, context: grpc.ServicerContext) -> kaggle_evaluation_proto.KaggleEvaluationResponse:
296
+ '''Handler for gRPC requests that deserializes arguments, calls a user-registered function for handling the
297
+ requested endpoint, then serializes and returns the response.
298
+
299
+ Args:
300
+ request: The KaggleEvaluationRequest protobuf message.
301
+ context: (Unused) gRPC context.
302
+
303
+ Returns:
304
+ The KaggleEvaluationResponse protobuf message.
305
+
306
+ Raises:
307
+ NotImplementedError if the caller has not registered a handler for the requested endpoint.
308
+ '''
309
+ if request.name not in self.listeners_map:
310
+ raise NotImplementedError(f'No listener for {request.name} was registered.')
311
+
312
+ args = map(_deserialize, request.args)
313
+ kwargs = {key: _deserialize(value) for key, value in request.kwargs.items()}
314
+ response_function = self.listeners_map[request.name]
315
+ response_payload = _serialize(response_function(*args, **kwargs))
316
+ return kaggle_evaluation_proto.KaggleEvaluationResponse(payload=response_payload)
317
+
318
+ def define_server(*endpoint_listeners: Tuple[Callable]) -> grpc.server:
319
+ '''Registers the endpoints that the container is able to respond to, then starts a server which listens for
320
+ those endpoints. The endpoints that need to be implemented will depend on the specific competition.
321
+
322
+ Args:
323
+ endpoint_listeners: Tuple of functions that define how requests to the endpoint of the function name should be
324
+ handled.
325
+
326
+ Returns:
327
+ The gRPC server object, which has been started. It should be stopped at exit time.
328
+
329
+ Raises:
330
+ ValueError if parameter values are invalid.
331
+ '''
332
+ if not endpoint_listeners:
333
+ raise ValueError('Must pass at least one endpoint listener, e.g. `predict`')
334
+ for func in endpoint_listeners:
335
+ if not isinstance(func, Callable):
336
+ raise ValueError('Endpoint listeners passed to `serve` must be functions')
337
+ if func.__name__ == '<lambda>':
338
+ raise ValueError('Functions passed as endpoint listeners must be named')
339
+
340
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=1), options=_GRPC_CHANNEL_OPTIONS)
341
+ kaggle_evaluation_grpc.add_KaggleEvaluationServiceServicer_to_server(KaggleEvaluationServiceServicer(endpoint_listeners), server)
342
+ server.add_insecure_port(f'[::]:{_GRPC_PORT}')
343
+ return server
kaggle_evaluation/core/templates.py ADDED
@@ -0,0 +1,114 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''Template for the two classes hosts should customize for each competition.'''
2
+
3
+ import abc
4
+ import os
5
+ import pathlib
6
+ import polars as pl
7
+ import time
8
+ import sys
9
+ import traceback
10
+ import warnings
11
+
12
+ from typing import Callable, Generator, Tuple
13
+
14
+ import kaggle_evaluation.core.base_gateway
15
+ import kaggle_evaluation.core.relay
16
+
17
+
18
+ _initial_import_time = time.time()
19
+ _issued_startup_time_warning = False
20
+
21
+
22
+ class Gateway(kaggle_evaluation.core.base_gateway.BaseGateway, abc.ABC):
23
+ '''
24
+ Template to start with when writing a new gateway.
25
+ In most cases, hosts should only need to write get_all_predictions.
26
+ There are two main methods for sending data to the inference_server hosts should understand:
27
+ - Small datasets: use `self.predict`. Competitors will receive the data passed to self.predict as
28
+ Python objects in memory. This is just a wrapper for self.client.send(); you can write additional
29
+ wrappers if necessary.
30
+ - Large datasets: it's much faster to send data via self.share_files, which is equivalent to making
31
+ files available via symlink. See base_gateway.BaseGateway.share_files for the full details.
32
+ '''
33
+
34
+ @abc.abstractmethod
35
+ def generate_data_batches(self) -> Generator:
36
+ ''' Used by the default implementation of `get_all_predictions` so we can
37
+ ensure `validate_prediction_batch` is run every time `predict` is called.
38
+
39
+ This method must yield both the batch of data to be sent to `predict` and a series
40
+ of row IDs to be sent to `validate_prediction_batch`.
41
+ '''
42
+ raise NotImplementedError
43
+
44
+ def get_all_predictions(self):
45
+ all_predictions = []
46
+ all_row_ids = []
47
+ for data_batch, row_ids in self.generate_data_batches():
48
+ predictions = self.predict(*data_batch)
49
+ predictions = pl.Series(self.target_column_name, predictions)
50
+ self.validate_prediction_batch(predictions, row_ids)
51
+ all_predictions.append(predictions)
52
+ all_row_ids.append(row_ids)
53
+ return all_predictions, all_row_ids
54
+
55
+ def predict(self, *args, **kwargs):
56
+ ''' self.predict will send all data in args and kwargs to the user container, and
57
+ instruct the user container to generate a `predict` response.
58
+ '''
59
+ try:
60
+ return self.client.send('predict', *args, **kwargs)
61
+ except Exception as e:
62
+ self.handle_server_error(e, 'predict')
63
+
64
+ def set_response_timeout_seconds(self, timeout_seconds: float):
65
+ # Also store timeout_seconds in an easy place for for competitor to access.
66
+ self.timeout_seconds = timeout_seconds
67
+ # Set a response deadline that will apply after the very first repsonse
68
+ self.client.endpoint_deadline_seconds = timeout_seconds
69
+
70
+ def run(self) -> pathlib.Path:
71
+ error = None
72
+ submission_path = None
73
+ try:
74
+ predictions, row_ids = self.get_all_predictions()
75
+ submission_path = self.write_submission(predictions, row_ids)
76
+ except kaggle_evaluation.core.base_gateway.GatewayRuntimeError as gre:
77
+ error = gre
78
+ except Exception:
79
+ # Get the full stack trace
80
+ exc_type, exc_value, exc_traceback = sys.exc_info()
81
+ error_str = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
82
+
83
+ error = kaggle_evaluation.core.base_gateway.GatewayRuntimeError(
84
+ kaggle_evaluation.core.base_gateway.GatewayRuntimeErrorType.GATEWAY_RAISED_EXCEPTION,
85
+ error_str
86
+ )
87
+
88
+ self.client.close()
89
+ if self.server:
90
+ self.server.stop(0)
91
+
92
+ if kaggle_evaluation.core.base_gateway.IS_RERUN:
93
+ self.write_result(error)
94
+ elif error:
95
+ # For local testing
96
+ raise error
97
+
98
+ return submission_path
99
+
100
+
101
+ class InferenceServer(abc.ABC):
102
+ '''
103
+ Base class for competition participants to inherit from when writing their submission. In most cases, users should
104
+ only need to implement a `predict` function or other endpoints to pass to this class's constructor, and hosts will
105
+ provide a mock Gateway for testing.
106
+ '''
107
+ def __init__(self, endpoint_listeners: Tuple[Callable]):
108
+ self.server = kaggle_evaluation.core.relay.define_server(endpoint_listeners)
109
+ self.client = None # The inference_server can have a client but it isn't typically necessary.
110
+
111
+ def serve(self):
112
+ self.server.start()
113
+ if os.getenv('KAGGLE_IS_COMPETITION_RERUN') is not None:
114
+ self.server.wait_for_termination() # This will block all other code
kaggle_evaluation/svg.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import inspect
2
+ import pathlib
3
+ from types import ModuleType
4
+
5
+ from kaggle_evaluation.core import relay, templates
6
+ from kaggle_evaluation.svg_gateway import SVGGateway
7
+
8
+
9
+ def test(model_cls: type, data_path: str | pathlib.Path | None = None) -> None:
10
+ '''Tests this competition's inference loop over the given Model class.
11
+
12
+ The provided Model class should have a `predict` function which accepts input(s)
13
+ and returns output(s) with the shapes and types required by this competition.
14
+ This function performs best-effort validation of this by running an inference
15
+ loop with a dummy test set over Model.predict.
16
+ By default the test set is taken from the `kaggle_evaluation` directory, but you
17
+ may override to another directory with the same test file structure via the
18
+ `data_path` arg.'''
19
+ print('Creating Model instance...')
20
+ model = model_cls()
21
+ if not hasattr(model, 'predict') or not inspect.ismethod(model.predict):
22
+ msg = f'Model does not have method predict.'
23
+ raise ValueError(msg)
24
+
25
+ print('Running inference tests...')
26
+ server = relay.define_server(model.predict)
27
+ server.start()
28
+ try:
29
+ gateway = SVGGateway(data_path)
30
+ submission_path = gateway.run()
31
+ print(f'Wrote test submission file to "{str(submission_path)}".')
32
+ except Exception as err:
33
+ raise err from None
34
+ finally:
35
+ server.stop(0)
36
+
37
+ print('Success!')
38
+
39
+
40
+ def _run_gateway() -> None:
41
+ '''Internal function for running the Gateway during a Kaggle scoring session.
42
+
43
+ Starts a scoring session which assumes existence of an Inference Server to return
44
+ inferences over the test set.'''
45
+ gateway = SVGGateway()
46
+ gateway.run()
47
+
48
+
49
+ def _run_inference_server(module: ModuleType) -> None:
50
+ '''Internal function for running the Inference Server during a Kaggle scoring session.
51
+
52
+ Takes the user's submitted, imported module and sets up the inference server exposing
53
+ their required method(s).'''
54
+ model = module.Model()
55
+ server = templates.InferenceServer(model.predict)
56
+ server.serve()
kaggle_evaluation/svg_constraints.py ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataclasses import dataclass, field
2
+
3
+ from defusedxml import ElementTree as etree
4
+
5
+
6
+ @dataclass(frozen=True)
7
+ class SVGConstraints:
8
+ """Defines constraints for validating SVG documents.
9
+
10
+ Attributes
11
+ ----------
12
+ max_svg_size : int, default=10000
13
+ Maximum allowed size of an SVG file in bytes.
14
+ allowed_elements : dict[str, set[str]]
15
+ Mapping of the allowed elements to the allowed attributes of each element.
16
+ """
17
+
18
+ max_svg_size: int = 10000
19
+ allowed_elements: dict[str, set[str]] = field(
20
+ default_factory=lambda: {
21
+ 'common': {
22
+ 'id',
23
+ 'clip-path',
24
+ 'clip-rule',
25
+ 'color',
26
+ 'color-interpolation',
27
+ 'color-interpolation-filters',
28
+ 'color-rendering',
29
+ 'display',
30
+ 'fill',
31
+ 'fill-opacity',
32
+ 'fill-rule',
33
+ 'filter',
34
+ 'flood-color',
35
+ 'flood-opacity',
36
+ 'lighting-color',
37
+ 'marker-end',
38
+ 'marker-mid',
39
+ 'marker-start',
40
+ 'mask',
41
+ 'opacity',
42
+ 'paint-order',
43
+ 'stop-color',
44
+ 'stop-opacity',
45
+ 'stroke',
46
+ 'stroke-dasharray',
47
+ 'stroke-dashoffset',
48
+ 'stroke-linecap',
49
+ 'stroke-linejoin',
50
+ 'stroke-miterlimit',
51
+ 'stroke-opacity',
52
+ 'stroke-width',
53
+ 'transform',
54
+ },
55
+ 'svg': {
56
+ 'width',
57
+ 'height',
58
+ 'viewBox',
59
+ 'preserveAspectRatio',
60
+ },
61
+ 'g': {'viewBox'},
62
+ 'defs': set(),
63
+ 'symbol': {'viewBox', 'x', 'y', 'width', 'height'},
64
+ 'use': {'x', 'y', 'width', 'height', 'href'},
65
+ 'marker': {
66
+ 'viewBox',
67
+ 'preserveAspectRatio',
68
+ 'refX',
69
+ 'refY',
70
+ 'markerUnits',
71
+ 'markerWidth',
72
+ 'markerHeight',
73
+ 'orient',
74
+ },
75
+ 'pattern': {
76
+ 'viewBox',
77
+ 'preserveAspectRatio',
78
+ 'x',
79
+ 'y',
80
+ 'width',
81
+ 'height',
82
+ 'patternUnits',
83
+ 'patternContentUnits',
84
+ 'patternTransform',
85
+ 'href',
86
+ },
87
+ 'linearGradient': {
88
+ 'x1',
89
+ 'x2',
90
+ 'y1',
91
+ 'y2',
92
+ 'gradientUnits',
93
+ 'gradientTransform',
94
+ 'spreadMethod',
95
+ 'href',
96
+ },
97
+ 'radialGradient': {
98
+ 'cx',
99
+ 'cy',
100
+ 'r',
101
+ 'fx',
102
+ 'fy',
103
+ 'fr',
104
+ 'gradientUnits',
105
+ 'gradientTransform',
106
+ 'spreadMethod',
107
+ 'href',
108
+ },
109
+ 'stop': {'offset'},
110
+ 'filter': {
111
+ 'x',
112
+ 'y',
113
+ 'width',
114
+ 'height',
115
+ 'filterUnits',
116
+ 'primitiveUnits',
117
+ },
118
+ 'feBlend': {'result', 'in', 'in2', 'mode'},
119
+ 'feColorMatrix': {'result', 'in', 'type', 'values'},
120
+ 'feComposite': {
121
+ 'result',
122
+ 'style',
123
+ 'in',
124
+ 'in2',
125
+ 'operator',
126
+ 'k1',
127
+ 'k2',
128
+ 'k3',
129
+ 'k4',
130
+ },
131
+ 'feFlood': {'result'},
132
+ 'feGaussianBlur': {
133
+ 'result',
134
+ 'in',
135
+ 'stdDeviation',
136
+ 'edgeMode',
137
+ },
138
+ 'feMerge': {
139
+ 'result',
140
+ 'x',
141
+ 'y',
142
+ 'width',
143
+ 'height',
144
+ 'result',
145
+ },
146
+ 'feMergeNode': {'result', 'in'},
147
+ 'feOffset': {'result', 'in', 'dx', 'dy'},
148
+ 'feTurbulence': {
149
+ 'result',
150
+ 'baseFrequency',
151
+ 'numOctaves',
152
+ 'seed',
153
+ 'stitchTiles',
154
+ 'type',
155
+ },
156
+ 'path': {'d'},
157
+ 'rect': {'x', 'y', 'width', 'height', 'rx', 'ry'},
158
+ 'circle': {'cx', 'cy', 'r'},
159
+ 'ellipse': {'cx', 'cy', 'rx', 'ry'},
160
+ 'line': {'x1', 'y1', 'x2', 'y2'},
161
+ 'polyline': {'points'},
162
+ 'polygon': {'points'},
163
+ }
164
+ )
165
+
166
+ def validate_svg(self, svg_code: str) -> None:
167
+ """Validates an SVG string against a set of predefined constraints.
168
+
169
+ Parameters
170
+ ----------
171
+ svg_code : str
172
+ The SVG string to validate.
173
+
174
+ Raises
175
+ ------
176
+ ValueError
177
+ If the SVG violates any of the defined constraints.
178
+ """
179
+ # Check file size
180
+ if len(svg_code.encode('utf-8')) > self.max_svg_size:
181
+ raise ValueError('SVG exceeds allowed size')
182
+
183
+ # Parse XML
184
+ tree = etree.fromstring(
185
+ svg_code.encode('utf-8'),
186
+ forbid_dtd=True,
187
+ forbid_entities=True,
188
+ forbid_external=True,
189
+ )
190
+
191
+ elements = set(self.allowed_elements.keys())
192
+
193
+ # Check elements and attributes
194
+ for element in tree.iter():
195
+ # Check for disallowed elements
196
+ tag_name = element.tag.split('}')[-1]
197
+ if tag_name not in elements:
198
+ raise ValueError(f'Disallowed element: {tag_name}')
199
+
200
+ # Check attributes
201
+ for attr, attr_value in element.attrib.items():
202
+ # Check for disallowed attributes
203
+ attr_name = attr.split('}')[-1]
204
+ if (
205
+ attr_name not in self.allowed_elements[tag_name]
206
+ and attr_name not in self.allowed_elements['common']
207
+ ):
208
+ raise ValueError(f'Disallowed attribute: {attr_name}')
209
+
210
+ # Check for embedded data
211
+ if 'data:' in attr_value.lower():
212
+ raise ValueError('Embedded data not allowed')
213
+ if ';base64' in attr_value:
214
+ raise ValueError('Base64 encoded content not allowed')
215
+
216
+ # Check that href attributes are internal references
217
+ if attr_name == 'href':
218
+ if not attr_value.startswith('#'):
219
+ raise ValueError(
220
+ f'Invalid href attribute in <{tag_name}>. Only internal references (starting with "#") are allowed. Found: "{attr_value}"'
221
+ )
222
+
223
+
224
+ if __name__ == '__main__':
225
+ svg_validator = SVGConstraints()
226
+
227
+ valid_svg = """
228
+ <svg width="100" height="100">
229
+ <circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
230
+ </svg>
231
+ """
232
+
233
+ invalid_size_svg = '<svg>' + ' ' * 6000 + '</svg>' # Exceeds default 5000 bytes
234
+
235
+ invalid_element_svg = """
236
+ <svg>
237
+ <script>alert('bad');</script>
238
+ </svg>
239
+ """
240
+
241
+ invalid_attribute_svg = """
242
+ <svg>
243
+ <rect width="100" height="100" onclick="alert('bad')"/>
244
+ </svg>
245
+ """
246
+
247
+ invalid_href_svg = """
248
+ <svg>
249
+ <use href="http://example.com/image.svg" />
250
+ </svg>
251
+ """
252
+
253
+ invalid_embedded_image_element_svg = """
254
+ <svg width="100" height="100">
255
+ <image href="data:image/png;base64,iVBOAAAANSUhEUgAAAAUAAAAFCAYAAACN==" width="50" height="50"/>
256
+ </svg>
257
+ """
258
+
259
+ invalid_data_uri_attribute_svg = """
260
+ <svg width="100" height="100">
261
+ <rect width="50" height="50" fill="url(data:image/png;base64,iVBOAAAANSUhEUgAAAAUAAAAFCAYAAACN==)" />
262
+ </svg>
263
+ """
264
+
265
+ print('Running SVG validation examples:')
266
+
267
+ print('\nValid SVG example:')
268
+ svg_validator.validate_svg(valid_svg)
269
+ print(' Validation successful!')
270
+
271
+ print('\nSVG exceeding size limit:')
272
+ try:
273
+ svg_validator.validate_svg(invalid_size_svg)
274
+ print(' Validation successful! (This should not happen)')
275
+ except ValueError as e:
276
+ print(f' Validation failed as expected with error: {e}')
277
+
278
+ print('\nSVG with disallowed element:')
279
+ try:
280
+ svg_validator.validate_svg(invalid_element_svg)
281
+ print(' Validation successful! (This should not happen)')
282
+ except ValueError as e:
283
+ print(f' Validation failed as expected with error: {e}')
284
+
285
+ print('\nSVG with disallowed attribute:')
286
+ try:
287
+ svg_validator.validate_svg(invalid_attribute_svg)
288
+ print(' Validation successful! (This should not happen)')
289
+ except ValueError as e:
290
+ print(f' Validation failed as expected with error: {e}')
291
+
292
+ print('\nSVG with invalid external href:')
293
+ try:
294
+ svg_validator.validate_svg(invalid_href_svg)
295
+ print(' Validation successful! (This should not happen)')
296
+ except ValueError as e:
297
+ print(f' Validation failed as expected with error: {e}')
298
+
299
+ print('\nSVG with disallowed <image> element:')
300
+ try:
301
+ svg_validator.validate_svg(invalid_embedded_image_element_svg)
302
+ print(' Validation successful! (This should not happen)')
303
+ except ValueError as e:
304
+ print(f' Validation failed as expected with error: {e}')
305
+
306
+ print('\nSVG with invalid data URI in attribute (fill):')
307
+ try:
308
+ svg_validator.validate_svg(invalid_data_uri_attribute_svg)
309
+ print(' Validation successful! (This should not happen)')
310
+ except ValueError as e:
311
+ print(f' Validation failed as expected with error: {e}')
kaggle_evaluation/svg_gateway.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Gateway notebook for SVG Image Generation"""
2
+
3
+ import os
4
+ import tempfile
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import pandas as pd
9
+ import polars as pl
10
+
11
+ from kaggle_evaluation.core.base_gateway import GatewayRuntimeError, GatewayRuntimeErrorType, IS_RERUN
12
+ import kaggle_evaluation.core.templates
13
+ from kaggle_evaluation.svg_constraints import SVGConstraints
14
+
15
+
16
+ class SVGGateway(kaggle_evaluation.core.templates.Gateway):
17
+ def __init__(self, data_path: str | Path | None = None):
18
+ super().__init__(target_column_name='svg')
19
+ self.set_response_timeout_seconds(60 * 5)
20
+ self.row_id_column_name = 'id'
21
+ self.data_path: Path = Path(data_path) if data_path else Path(__file__).parent
22
+ self.constraints: SVGConstraints = SVGConstraints()
23
+
24
+ def generate_data_batches(self):
25
+ test = pl.read_csv(self.data_path / 'test.csv')
26
+ for _, group in test.group_by('id'):
27
+ yield group.item(0, 0), group.item(0, 1) # id, description
28
+
29
+ def get_all_predictions(self):
30
+ row_ids, predictions = [], []
31
+ for id, description in self.generate_data_batches():
32
+ svg = self.predict(description)
33
+ if not isinstance(svg, str):
34
+ raise ValueError("Predicted SVG must have `str` type.")
35
+ self.validate(svg)
36
+ row_ids.append(id)
37
+ predictions.append(svg)
38
+
39
+ return predictions, row_ids
40
+
41
+ def validate(self, svg: str):
42
+ try:
43
+ self.constraints.validate_svg(svg)
44
+ except ValueError as err:
45
+ msg = f'SVG failed validation: {str(err)}'
46
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, msg)
47
+
48
+ def write_submission(self, predictions: list, row_ids: list) -> Path:
49
+ predictions = pl.DataFrame(
50
+ data={
51
+ self.row_id_column_name: row_ids,
52
+ self.target_column_name: predictions,
53
+ }
54
+ )
55
+
56
+ submission_path = Path('/kaggle/working/submission.csv')
57
+ if not IS_RERUN:
58
+ with tempfile.NamedTemporaryFile(prefix='kaggle-evaluation-submission-', suffix='.csv', delete=False, mode='w+') as f:
59
+ submission_path = Path(f.name)
60
+
61
+ predictions.write_csv(submission_path)
62
+
63
+ return submission_path
kaggle_evaluation/svg_gateway.py~ ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Gateway notebook for SVG Image Generation"""
2
+
3
+ import os
4
+ import tempfile
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import pandas as pd
9
+ import polars as pl
10
+
11
+ from kaggle_evaluation.core.base_gateway import GatewayRuntimeError, GatewayRuntimeErrorType, IS_RERUN
12
+ import kaggle_evaluation.core.templates
13
+ from kaggle_evaluation.svg_constraints import SVGConstraints
14
+
15
+
16
+ class SVGGateway(kaggle_evaluation.core.templates.Gateway):
17
+ def __init__(self, data_path: str | Path | None = None):
18
+ super().__init__(target_column_name='svg')
19
+ self.set_response_timeout_seconds(60 * 5)
20
+ self.row_id_column_name = 'id'
21
+ self.data_path: Path = Path(data_path) if data_path else Path(__file__).parent
22
+ self.constraints: SVGConstraints = SVGConstraints()
23
+
24
+ def generate_data_batches(self):
25
+ test = pl.read_csv(self.data_path / 'test.csv')
26
+ for _, group in test.group_by('id'):
27
+ yield group.item(0, 0), group.item(0, 1) # id, description
28
+
29
+ def get_all_predictions(self):
30
+ row_ids, predictions = [], []
31
+ for id, description in self.generate_data_batches():
32
+ svg = self.predict(description)
33
+ self.validate(svg)
34
+ row_ids.append(id)
35
+ predictions.append(svg)
36
+
37
+ return predictions, row_ids
38
+
39
+ def validate(self, svg: str):
40
+ try:
41
+ self.constraints.validate_svg(svg)
42
+ except ValueError as err:
43
+ msg = f'SVG failed validation: {str(err)}'
44
+ raise GatewayRuntimeError(GatewayRuntimeErrorType.INVALID_SUBMISSION, msg)
45
+
46
+ def write_submission(self, predictions: list, row_ids: list) -> Path:
47
+ predictions = pl.DataFrame(
48
+ data={
49
+ self.row_id_column_name: row_ids,
50
+ self.target_column_name: predictions,
51
+ }
52
+ )
53
+
54
+ submission_path = Path('/kaggle/working/submission.csv')
55
+ if not IS_RERUN:
56
+ with tempfile.NamedTemporaryFile(prefix='kaggle-evaluation-submission-', suffix='.csv', delete=False, mode='w+') as f:
57
+ submission_path = Path(f.name)
58
+
59
+ predictions.write_csv(submission_path)
60
+
61
+ return submission_path
kaggle_evaluation/test.csv ADDED
@@ -0,0 +1 @@
 
 
1
+ id,description
metric.py ADDED
@@ -0,0 +1,558 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import ast
2
+ import io
3
+ import math
4
+ import statistics
5
+ import string
6
+
7
+ import cairosvg
8
+ import clip
9
+ import cv2
10
+ import kagglehub
11
+ import matplotlib.pyplot as plt
12
+ import numpy as np
13
+ import pandas as pd
14
+ import torch
15
+ import torch.nn as nn
16
+ from more_itertools import chunked
17
+ from PIL import Image, ImageFilter
18
+ from transformers import (
19
+ AutoProcessor,
20
+ BitsAndBytesConfig,
21
+ PaliGemmaForConditionalGeneration,
22
+ )
23
+
24
+ svg_constraints = kagglehub.package_import('metric/svg-constraints')
25
+
26
+
27
+ class ParticipantVisibleError(Exception):
28
+ pass
29
+
30
+
31
+ def score(
32
+ solution: pd.DataFrame, submission: pd.DataFrame, row_id_column_name: str, random_seed: int = 0
33
+ ) -> float:
34
+ """Calculates a fidelity score by comparing generated SVG images to target text descriptions.
35
+
36
+ Parameters
37
+ ----------
38
+ solution : pd.DataFrame
39
+ A DataFrame containing target questions, choices, and answers about an SVG image.
40
+ submission : pd.DataFrame
41
+ A DataFrame containing generated SVG strings. Must have a column named 'svg'.
42
+ row_id_column_name : str
43
+ The name of the column containing row identifiers. This column is removed before scoring.
44
+ random_seed : int
45
+ A seed to set the random state.
46
+
47
+ Returns
48
+ -------
49
+ float
50
+ The mean fidelity score (a value between 0 and 1) representing the average similarity between the generated SVGs and their descriptions.
51
+ A higher score indicates better fidelity.
52
+
53
+ Raises
54
+ ------
55
+ ParticipantVisibleError
56
+ If the 'svg' column in the submission DataFrame is not of string type or if validation of the SVG fails.
57
+
58
+ Examples
59
+ --------
60
+ >>> import pandas as pd
61
+ >>> solution = pd.DataFrame({
62
+ ... 'id': ["abcde"],
63
+ ... 'question': ['["Is there a red circle?", "What shape is present?"]'],
64
+ ... 'choices': ['[["yes", "no"], ["square", "circle", "triangle", "hexagon"]]'],
65
+ ... 'answer': ['["yes", "circle"]'],
66
+ ... })
67
+ >>> submission = pd.DataFrame({
68
+ ... 'id': ["abcde"],
69
+ ... 'svg': ['<svg viewBox="0 0 100 100"><circle cx="50" cy="50" r="40" fill="red"/></svg>'],
70
+ ... })
71
+ >>> score(solution, submission, 'row_id', random_seed=42)
72
+ 0...
73
+ """
74
+ # Convert solution fields to list dtypes and expand
75
+ for colname in ['question', 'choices', 'answer']:
76
+ solution[colname] = solution[colname].apply(ast.literal_eval)
77
+ solution = solution.explode(['question', 'choices', 'answer'])
78
+
79
+ # Validate
80
+ if not pd.api.types.is_string_dtype(submission.loc[:, 'svg']):
81
+ raise ParticipantVisibleError('svg must be a string.')
82
+
83
+ # Check that SVG code meets defined constraints
84
+ constraints = svg_constraints.SVGConstraints()
85
+ try:
86
+ for svg in submission.loc[:, 'svg']:
87
+ constraints.validate_svg(svg)
88
+ except:
89
+ raise ParticipantVisibleError('SVG code violates constraints.')
90
+
91
+ # Score
92
+ vqa_evaluator = VQAEvaluator()
93
+ aesthetic_evaluator = AestheticEvaluator()
94
+
95
+ results = []
96
+ rng = np.random.RandomState(random_seed)
97
+ try:
98
+ df = solution.merge(submission, on='id')
99
+ for i, (_, group) in enumerate(df.loc[
100
+ :, ['id', 'question', 'choices', 'answer', 'svg']
101
+ ].groupby('id')):
102
+ questions, choices, answers, svg = [
103
+ group[col_name].to_list()
104
+ for col_name in group.drop('id', axis=1).columns
105
+ ]
106
+ svg = svg[0] # unpack singleton from list
107
+ group_seed = rng.randint(0, np.iinfo(np.int32).max)
108
+ image_processor = ImageProcessor(image=svg_to_png(svg), seed=group_seed).apply()
109
+ image = image_processor.image.copy()
110
+ aesthetic_score = aesthetic_evaluator.score(image)
111
+ vqa_score = vqa_evaluator.score(questions, choices, answers, image)
112
+ image_processor.reset().apply_random_crop_resize().apply_jpeg_compression(quality=90)
113
+ ocr_score = vqa_evaluator.ocr(image_processor.image)
114
+ instance_score = (
115
+ harmonic_mean(vqa_score, aesthetic_score, beta=0.5) * ocr_score
116
+ )
117
+ results.append(instance_score)
118
+
119
+ except:
120
+ raise ParticipantVisibleError('SVG failed to score.')
121
+
122
+ fidelity = statistics.mean(results)
123
+ return float(fidelity)
124
+
125
+
126
+ class VQAEvaluator:
127
+ """Evaluates images based on their similarity to a given text description using multiple choice questions."""
128
+
129
+ def __init__(self):
130
+ self.quantization_config = BitsAndBytesConfig(
131
+ load_in_4bit=True,
132
+ bnb_4bit_quant_type='nf4',
133
+ bnb_4bit_use_double_quant=True,
134
+ bnb_4bit_compute_dtype=torch.float16,
135
+ )
136
+ self.letters = string.ascii_uppercase
137
+ self.model_path = kagglehub.model_download(
138
+ 'google/paligemma-2/transformers/paligemma2-10b-mix-448'
139
+ )
140
+ self.processor = AutoProcessor.from_pretrained(self.model_path)
141
+ self.model = PaliGemmaForConditionalGeneration.from_pretrained(
142
+ self.model_path,
143
+ low_cpu_mem_usage=True,
144
+ quantization_config=self.quantization_config,
145
+ ).to('cuda')
146
+
147
+ def score(self, questions, choices, answers, image, n=4):
148
+ scores = []
149
+ batches = (chunked(qs, n) for qs in [questions, choices, answers])
150
+ for question_batch, choice_batch, answer_batch in zip(*batches, strict=True):
151
+ scores.extend(
152
+ self.score_batch(
153
+ image,
154
+ question_batch,
155
+ choice_batch,
156
+ answer_batch,
157
+ )
158
+ )
159
+ return statistics.mean(scores)
160
+
161
+ def score_batch(
162
+ self,
163
+ image: Image.Image,
164
+ questions: list[str],
165
+ choices_list: list[list[str]],
166
+ answers: list[str],
167
+ ) -> list[float]:
168
+ """Evaluates the image based on multiple choice questions and answers.
169
+
170
+ Parameters
171
+ ----------
172
+ image : PIL.Image.Image
173
+ The image to evaluate.
174
+ questions : list[str]
175
+ List of questions about the image.
176
+ choices_list : list[list[str]]
177
+ List of lists of possible answer choices, corresponding to each question.
178
+ answers : list[str]
179
+ List of correct answers from the choices, corresponding to each question.
180
+
181
+ Returns
182
+ -------
183
+ list[float]
184
+ List of scores (values between 0 and 1) representing the probability of the correct answer for each question.
185
+ """
186
+ prompts = [
187
+ self.format_prompt(question, choices)
188
+ for question, choices in zip(questions, choices_list, strict=True)
189
+ ]
190
+ batched_choice_probabilities = self.get_choice_probability(
191
+ image, prompts, choices_list
192
+ )
193
+
194
+ scores = []
195
+ for i, _ in enumerate(questions):
196
+ choice_probabilities = batched_choice_probabilities[i]
197
+ answer = answers[i]
198
+ answer_probability = 0.0
199
+ for choice, prob in choice_probabilities.items():
200
+ if choice == answer:
201
+ answer_probability = prob
202
+ break
203
+ scores.append(answer_probability)
204
+
205
+ return scores
206
+
207
+ def format_prompt(self, question: str, choices: list[str]) -> str:
208
+ prompt = f'<image>answer en Question: {question}\nChoices:\n'
209
+ for i, choice in enumerate(choices):
210
+ prompt += f'{self.letters[i]}. {choice}\n'
211
+ return prompt
212
+
213
+ def mask_choices(self, logits, choices_list):
214
+ """Masks logits for the first token of each choice letter for each question in the batch."""
215
+ batch_size = logits.shape[0]
216
+ masked_logits = torch.full_like(logits, float('-inf'))
217
+
218
+ for batch_idx in range(batch_size):
219
+ choices = choices_list[batch_idx]
220
+ for i in range(len(choices)):
221
+ letter_token = self.letters[i]
222
+
223
+ first_token = self.processor.tokenizer.encode(
224
+ letter_token, add_special_tokens=False
225
+ )[0]
226
+ first_token_with_space = self.processor.tokenizer.encode(
227
+ ' ' + letter_token, add_special_tokens=False
228
+ )[0]
229
+
230
+ if isinstance(first_token, int):
231
+ masked_logits[batch_idx, first_token] = logits[
232
+ batch_idx, first_token
233
+ ]
234
+ if isinstance(first_token_with_space, int):
235
+ masked_logits[batch_idx, first_token_with_space] = logits[
236
+ batch_idx, first_token_with_space
237
+ ]
238
+
239
+ return masked_logits
240
+
241
+ def get_choice_probability(self, image, prompts, choices_list) -> list[dict]:
242
+ inputs = self.processor(
243
+ images=[image] * len(prompts),
244
+ text=prompts,
245
+ return_tensors='pt',
246
+ padding='longest',
247
+ ).to('cuda')
248
+
249
+ with torch.no_grad():
250
+ outputs = self.model(**inputs)
251
+ logits = outputs.logits[:, -1, :] # Logits for the last (predicted) token
252
+ masked_logits = self.mask_choices(logits, choices_list)
253
+ probabilities = torch.softmax(masked_logits, dim=-1)
254
+
255
+ batched_choice_probabilities = []
256
+ for batch_idx in range(len(prompts)):
257
+ choice_probabilities = {}
258
+ choices = choices_list[batch_idx]
259
+ for i, choice in enumerate(choices):
260
+ letter_token = self.letters[i]
261
+ first_token = self.processor.tokenizer.encode(
262
+ letter_token, add_special_tokens=False
263
+ )[0]
264
+ first_token_with_space = self.processor.tokenizer.encode(
265
+ ' ' + letter_token, add_special_tokens=False
266
+ )[0]
267
+
268
+ prob = 0.0
269
+ if isinstance(first_token, int):
270
+ prob += probabilities[batch_idx, first_token].item()
271
+ if isinstance(first_token_with_space, int):
272
+ prob += probabilities[batch_idx, first_token_with_space].item()
273
+ choice_probabilities[choice] = prob
274
+
275
+ # Renormalize probabilities for each question
276
+ total_prob = sum(choice_probabilities.values())
277
+ if total_prob > 0:
278
+ renormalized_probabilities = {
279
+ choice: prob / total_prob
280
+ for choice, prob in choice_probabilities.items()
281
+ }
282
+ else:
283
+ renormalized_probabilities = (
284
+ choice_probabilities # Avoid division by zero if total_prob is 0
285
+ )
286
+ batched_choice_probabilities.append(renormalized_probabilities)
287
+
288
+ return batched_choice_probabilities
289
+
290
+ def ocr(self, image, free_chars=4):
291
+ inputs = (
292
+ self.processor(
293
+ text='<image>ocr\n',
294
+ images=image,
295
+ return_tensors='pt',
296
+ )
297
+ .to(torch.float16)
298
+ .to(self.model.device)
299
+ )
300
+ input_len = inputs['input_ids'].shape[-1]
301
+
302
+ with torch.inference_mode():
303
+ outputs = self.model.generate(**inputs, max_new_tokens=32, do_sample=False)
304
+ outputs = outputs[0][input_len:]
305
+ decoded = self.processor.decode(outputs, skip_special_tokens=True)
306
+
307
+ num_char = len(decoded)
308
+
309
+ # Exponentially decreasing towards 0.0 if more than free_chars detected
310
+ return min(1.0, math.exp(-num_char + free_chars))
311
+
312
+
313
+ class AestheticPredictor(nn.Module):
314
+ def __init__(self, input_size):
315
+ super().__init__()
316
+ self.input_size = input_size
317
+ self.layers = nn.Sequential(
318
+ nn.Linear(self.input_size, 1024),
319
+ nn.Dropout(0.2),
320
+ nn.Linear(1024, 128),
321
+ nn.Dropout(0.2),
322
+ nn.Linear(128, 64),
323
+ nn.Dropout(0.1),
324
+ nn.Linear(64, 16),
325
+ nn.Linear(16, 1),
326
+ )
327
+
328
+ def forward(self, x):
329
+ return self.layers(x)
330
+
331
+
332
+ class AestheticEvaluator:
333
+ def __init__(self):
334
+ self.model_path = 'improved-aesthetic-predictor/sac+logos+ava1-l14-linearMSE.pth'
335
+ self.clip_model_path = 'ViT-L/14'
336
+ self.predictor, self.clip_model, self.preprocessor = self.load()
337
+
338
+ def load(self):
339
+ """Loads the aesthetic predictor model and CLIP model."""
340
+ state_dict = torch.load(self.model_path, weights_only=True, map_location='cuda')
341
+
342
+ # CLIP embedding dim is 768 for CLIP ViT L 14
343
+ predictor = AestheticPredictor(768)
344
+ predictor.load_state_dict(state_dict)
345
+ predictor.to('cuda')
346
+ predictor.eval()
347
+ clip_model, preprocessor = clip.load(self.clip_model_path, device='cuda')
348
+
349
+ return predictor, clip_model, preprocessor
350
+
351
+ def score(self, image: Image.Image) -> float:
352
+ """Predicts the CLIP aesthetic score of an image."""
353
+ image = self.preprocessor(image).unsqueeze(0).to('cuda')
354
+
355
+ with torch.no_grad():
356
+ image_features = self.clip_model.encode_image(image)
357
+ # l2 normalize
358
+ image_features /= image_features.norm(dim=-1, keepdim=True)
359
+ image_features = image_features.cpu().detach().numpy()
360
+
361
+ score = self.predictor(torch.from_numpy(image_features).to('cuda').float())
362
+
363
+ return score.item() / 10.0 # scale to [0, 1]
364
+
365
+
366
+ def harmonic_mean(a: float, b: float, beta: float = 1.0) -> float:
367
+ """
368
+ Calculate the harmonic mean of two values, weighted using a beta parameter.
369
+
370
+ Args:
371
+ a: First value (e.g., precision)
372
+ b: Second value (e.g., recall)
373
+ beta: Weighting parameter
374
+
375
+ Returns:
376
+ Weighted harmonic mean
377
+ """
378
+ # Handle zero values to prevent division by zero
379
+ if a <= 0 or b <= 0:
380
+ return 0.0
381
+ return (1 + beta**2) * (a * b) / (beta**2 * a + b)
382
+
383
+
384
+ def svg_to_png(svg_code: str, size: tuple = (384, 384)) -> Image.Image:
385
+ """
386
+ Converts an SVG string to a PNG image using CairoSVG.
387
+
388
+ If the SVG does not define a `viewBox`, it will add one using the provided size.
389
+
390
+ Parameters
391
+ ----------
392
+ svg_code : str
393
+ The SVG string to convert.
394
+ size : tuple[int, int], default=(384, 384)
395
+ The desired size of the output PNG image (width, height).
396
+
397
+ Returns
398
+ -------
399
+ PIL.Image.Image
400
+ The generated PNG image.
401
+ """
402
+ # Ensure SVG has proper size attributes
403
+ if 'viewBox' not in svg_code:
404
+ svg_code = svg_code.replace('<svg', f'<svg viewBox="0 0 {size[0]} {size[1]}"')
405
+
406
+ # Convert SVG to PNG
407
+ png_data = cairosvg.svg2png(bytestring=svg_code.encode('utf-8'))
408
+ return Image.open(io.BytesIO(png_data)).convert('RGB').resize(size)
409
+
410
+
411
+ class ImageProcessor:
412
+ def __init__(self, image: Image.Image, seed=None):
413
+ """Initialize with either a path to an image or a PIL Image object."""
414
+ self.image = image
415
+ self.original_image = self.image.copy()
416
+ if seed is not None:
417
+ self.rng = np.random.RandomState(seed)
418
+ else:
419
+ self.rng = np.random
420
+
421
+ def reset(self):
422
+ self.image = self.original_image.copy()
423
+ return self
424
+
425
+ def visualize_comparison(
426
+ self,
427
+ original_name='Original',
428
+ processed_name='Processed',
429
+ figsize=(10, 5),
430
+ show=True,
431
+ ):
432
+ """Display original and processed images side by side."""
433
+ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=figsize)
434
+ ax1.imshow(np.asarray(self.original_image))
435
+ ax1.set_title(original_name)
436
+ ax1.axis('off')
437
+
438
+ ax2.imshow(np.asarray(self.image))
439
+ ax2.set_title(processed_name)
440
+ ax2.axis('off')
441
+
442
+ title = f'{original_name} vs {processed_name}'
443
+ fig.suptitle(title)
444
+ fig.tight_layout()
445
+ if show:
446
+ plt.show()
447
+ return fig
448
+
449
+ def apply_median_filter(self, size=3):
450
+ """Apply median filter to remove outlier pixel values.
451
+
452
+ Args:
453
+ size: Size of the median filter window.
454
+ """
455
+ self.image = self.image.filter(ImageFilter.MedianFilter(size=size))
456
+ return self
457
+
458
+ def apply_bilateral_filter(self, d=9, sigma_color=75, sigma_space=75):
459
+ """Apply bilateral filter to smooth while preserving edges.
460
+
461
+ Args:
462
+ d: Diameter of each pixel neighborhood
463
+ sigma_color: Filter sigma in the color space
464
+ sigma_space: Filter sigma in the coordinate space
465
+ """
466
+ # Convert PIL Image to numpy array for OpenCV
467
+ img_array = np.asarray(self.image)
468
+
469
+ # Apply bilateral filter
470
+ filtered = cv2.bilateralFilter(img_array, d, sigma_color, sigma_space)
471
+
472
+ # Convert back to PIL Image
473
+ self.image = Image.fromarray(filtered)
474
+ return self
475
+
476
+ def apply_fft_low_pass(self, cutoff_frequency=0.5):
477
+ """Apply low-pass filter in the frequency domain using FFT.
478
+
479
+ Args:
480
+ cutoff_frequency: Normalized cutoff frequency (0-1).
481
+ Lower values remove more high frequencies.
482
+ """
483
+ # Convert to numpy array, ensuring float32 for FFT
484
+ img_array = np.array(self.image, dtype=np.float32)
485
+
486
+ # Process each color channel separately
487
+ result = np.zeros_like(img_array)
488
+ for i in range(3): # For RGB channels
489
+ # Apply FFT
490
+ f = np.fft.fft2(img_array[:, :, i])
491
+ fshift = np.fft.fftshift(f)
492
+
493
+ # Create a low-pass filter mask
494
+ rows, cols = img_array[:, :, i].shape
495
+ crow, ccol = rows // 2, cols // 2
496
+ mask = np.zeros((rows, cols), np.float32)
497
+ r = int(min(crow, ccol) * cutoff_frequency)
498
+ center = [crow, ccol]
499
+ x, y = np.ogrid[:rows, :cols]
500
+ mask_area = (x - center[0]) ** 2 + (y - center[1]) ** 2 <= r * r
501
+ mask[mask_area] = 1
502
+
503
+ # Apply mask and inverse FFT
504
+ fshift_filtered = fshift * mask
505
+ f_ishift = np.fft.ifftshift(fshift_filtered)
506
+ img_back = np.fft.ifft2(f_ishift)
507
+ img_back = np.real(img_back)
508
+
509
+ result[:, :, i] = img_back
510
+
511
+ # Clip to 0-255 range and convert to uint8 after processing all channels
512
+ result = np.clip(result, 0, 255).astype(np.uint8)
513
+
514
+ # Convert back to PIL Image
515
+ self.image = Image.fromarray(result)
516
+ return self
517
+
518
+ def apply_jpeg_compression(self, quality=85):
519
+ """Apply JPEG compression.
520
+
521
+ Args:
522
+ quality: JPEG quality (0-95). Lower values increase compression.
523
+ """
524
+ buffer = io.BytesIO()
525
+ self.image.save(buffer, format='JPEG', quality=quality)
526
+ buffer.seek(0)
527
+ self.image = Image.open(buffer)
528
+ return self
529
+
530
+ def apply_random_crop_resize(self, crop_percent=0.05):
531
+ """Randomly crop and resize back to original dimensions.
532
+
533
+ Args:
534
+ crop_percent: Percentage of image to crop (0-0.4).
535
+ """
536
+ width, height = self.image.size
537
+ crop_pixels_w = int(width * crop_percent)
538
+ crop_pixels_h = int(height * crop_percent)
539
+
540
+ left = self.rng.randint(0, crop_pixels_w + 1)
541
+ top = self.rng.randint(0, crop_pixels_h + 1)
542
+ right = width - self.rng.randint(0, crop_pixels_w + 1)
543
+ bottom = height - self.rng.randint(0, crop_pixels_h + 1)
544
+
545
+ self.image = self.image.crop((left, top, right, bottom))
546
+ self.image = self.image.resize((width, height), Image.BILINEAR)
547
+ return self
548
+
549
+ def apply(self):
550
+ """Apply an ensemble of defenses."""
551
+ return (
552
+ self.apply_random_crop_resize(crop_percent=0.03)
553
+ .apply_jpeg_compression(quality=95)
554
+ .apply_median_filter(size=9)
555
+ .apply_fft_low_pass(cutoff_frequency=0.5)
556
+ .apply_bilateral_filter(d=5, sigma_color=75, sigma_space=75)
557
+ .apply_jpeg_compression(quality=92)
558
+ )
requirements.txt ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ kagglehub
2
+ polars
3
+ grpcio
4
+ numpy
5
+ pandas
6
+ pyarrow
7
+ protobuf
8
+ defusedxml
9
+ keras
10
+ cairosvg
11
+ bitsandbytes
12
+ opencv-python
13
+ matplotlib
14
+ transformers
15
+ accelerate
16
+ openai
17
+ tqdm
18
+ dotenv
19
+
20
+ # pip install 'tensorflow[and-cuda]'
21
+ # pip install git+https://github.com/openai/CLIP.git
22
+ # sudo apt-get update
23
+ # sudo apt-get install -y build-essential
starter.ipynb ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": 2,
6
+ "metadata": {},
7
+ "outputs": [
8
+ {
9
+ "name": "stderr",
10
+ "output_type": "stream",
11
+ "text": [
12
+ "/home/user/miniconda3/envs/dwl/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
13
+ " from .autonotebook import tqdm as notebook_tqdm\n"
14
+ ]
15
+ },
16
+ {
17
+ "data": {
18
+ "text/html": [
19
+ "<div><style>\n",
20
+ ".dataframe > thead > tr,\n",
21
+ ".dataframe > tbody > tr {\n",
22
+ " text-align: right;\n",
23
+ " white-space: pre-wrap;\n",
24
+ "}\n",
25
+ "</style>\n",
26
+ "<small>shape: (5, 2)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>id</th><th>description</th></tr><tr><td>str</td><td>str</td></tr></thead><tbody><tr><td>&quot;02d892&quot;</td><td>&quot;a purple forest at dusk&quot;</td></tr><tr><td>&quot;0dcd2e&quot;</td><td>&quot;gray wool coat with a faux fur…</td></tr><tr><td>&quot;1e9ac1&quot;</td><td>&quot;a lighthouse overlooking the o…</td></tr><tr><td>&quot;2b25db&quot;</td><td>&quot;burgundy corduroy pants with p…</td></tr><tr><td>&quot;4e6a54&quot;</td><td>&quot;orange corduroy overalls&quot;</td></tr></tbody></table></div>"
27
+ ],
28
+ "text/plain": [
29
+ "shape: (5, 2)\n",
30
+ "β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”\n",
31
+ "β”‚ id ┆ description β”‚\n",
32
+ "β”‚ --- ┆ --- β”‚\n",
33
+ "β”‚ str ┆ str β”‚\n",
34
+ "β•žβ•β•β•β•β•β•β•β•β•ͺ═════════════════════════════════║\n",
35
+ "β”‚ 02d892 ┆ a purple forest at dusk β”‚\n",
36
+ "β”‚ 0dcd2e ┆ gray wool coat with a faux fur… β”‚\n",
37
+ "β”‚ 1e9ac1 ┆ a lighthouse overlooking the o… β”‚\n",
38
+ "β”‚ 2b25db ┆ burgundy corduroy pants with p… β”‚\n",
39
+ "β”‚ 4e6a54 ┆ orange corduroy overalls β”‚\n",
40
+ "β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜"
41
+ ]
42
+ },
43
+ "execution_count": 2,
44
+ "metadata": {},
45
+ "output_type": "execute_result"
46
+ }
47
+ ],
48
+ "source": [
49
+ "# We can load and explore the competition's train set to get a feel for the data.\n",
50
+ "# We're not going to export this cell as it's not needed for our exported inferenceable model.\n",
51
+ "\n",
52
+ "import kagglehub\n",
53
+ "import polars as pl\n",
54
+ "\n",
55
+ "train_path = kagglehub.competition_download('drawing-with-llms', 'train.csv')\n",
56
+ "train = pl.read_csv(train_path)\n",
57
+ "\n",
58
+ "train.head()"
59
+ ]
60
+ },
61
+ {
62
+ "cell_type": "code",
63
+ "execution_count": 3,
64
+ "metadata": {},
65
+ "outputs": [],
66
+ "source": [
67
+ "class Model:\n",
68
+ " def __init__(self):\n",
69
+ " '''Optional constructor, performs any setup logic, model instantiation, etc.'''\n",
70
+ " pass\n",
71
+ " \n",
72
+ " def predict(self, prompt: str) -> str:\n",
73
+ " '''Generates SVG which produces an image described by the prompt.\n",
74
+ "\n",
75
+ " Args:\n",
76
+ " prompt (str): A prompt describing an image\n",
77
+ " Returns:\n",
78
+ " String of valid SVG code.\n",
79
+ " '''\n",
80
+ " # Renders a simple circle regardless of input\n",
81
+ " return '<svg width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"red\" /></svg>'"
82
+ ]
83
+ },
84
+ {
85
+ "cell_type": "code",
86
+ "execution_count": 4,
87
+ "metadata": {},
88
+ "outputs": [
89
+ {
90
+ "name": "stdout",
91
+ "output_type": "stream",
92
+ "text": [
93
+ "<svg width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"red\" /></svg>\n"
94
+ ]
95
+ },
96
+ {
97
+ "data": {
98
+ "image/svg+xml": [
99
+ "<svg width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><circle cx=\"50\" cy=\"50\" r=\"40\" fill=\"red\"/></svg>"
100
+ ],
101
+ "text/plain": [
102
+ "<IPython.core.display.SVG object>"
103
+ ]
104
+ },
105
+ "metadata": {},
106
+ "output_type": "display_data"
107
+ }
108
+ ],
109
+ "source": [
110
+ "from IPython.display import SVG\n",
111
+ "\n",
112
+ "model = Model()\n",
113
+ "svg = model.predict('a goose winning a gold medal')\n",
114
+ "\n",
115
+ "print(svg)\n",
116
+ "display(SVG(svg))"
117
+ ]
118
+ },
119
+ {
120
+ "cell_type": "code",
121
+ "execution_count": 6,
122
+ "metadata": {},
123
+ "outputs": [
124
+ {
125
+ "data": {
126
+ "text/plain": [
127
+ "['RN50',\n",
128
+ " 'RN101',\n",
129
+ " 'RN50x4',\n",
130
+ " 'RN50x16',\n",
131
+ " 'RN50x64',\n",
132
+ " 'ViT-B/32',\n",
133
+ " 'ViT-B/16',\n",
134
+ " 'ViT-L/14',\n",
135
+ " 'ViT-L/14@336px']"
136
+ ]
137
+ },
138
+ "execution_count": 6,
139
+ "metadata": {},
140
+ "output_type": "execute_result"
141
+ }
142
+ ],
143
+ "source": [
144
+ "import clip\n",
145
+ "clip.available_models()"
146
+ ]
147
+ },
148
+ {
149
+ "cell_type": "code",
150
+ "execution_count": 7,
151
+ "metadata": {},
152
+ "outputs": [
153
+ {
154
+ "name": "stderr",
155
+ "output_type": "stream",
156
+ "text": [
157
+ "2025-04-20 13:55:34.589770: E external/local_xla/xla/stream_executor/cuda/cuda_fft.cc:467] Unable to register cuFFT factory: Attempting to register factory for plugin cuFFT when one has already been registered\n",
158
+ "WARNING: All log messages before absl::InitializeLog() is called are written to STDERR\n",
159
+ "E0000 00:00:1745171734.600777 13214 cuda_dnn.cc:8579] Unable to register cuDNN factory: Attempting to register factory for plugin cuDNN when one has already been registered\n",
160
+ "E0000 00:00:1745171734.603957 13214 cuda_blas.cc:1407] Unable to register cuBLAS factory: Attempting to register factory for plugin cuBLAS when one has already been registered\n",
161
+ "W0000 00:00:1745171734.615566 13214 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
162
+ "W0000 00:00:1745171734.615584 13214 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
163
+ "W0000 00:00:1745171734.615585 13214 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
164
+ "W0000 00:00:1745171734.615586 13214 computation_placer.cc:177] computation placer already registered. Please check linkage and avoid linking the same target more than once.\n",
165
+ "2025-04-20 13:55:34.618659: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.\n",
166
+ "To enable the following instructions: AVX2 FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.\n",
167
+ "Using a slow image processor as `use_fast` is unset and a slow processor was saved with this model. `use_fast=True` will be the default behavior in v4.52, even if the model was saved with a slow processor. This will result in minor differences in outputs. You'll still be able to use a slow processor with `use_fast=False`.\n",
168
+ "Loading checkpoint shards: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 4/4 [00:18<00:00, 4.68s/it]\n"
169
+ ]
170
+ }
171
+ ],
172
+ "source": [
173
+ "import pandas as pd\n",
174
+ "import importlib\n",
175
+ "metric = importlib.import_module('metric')\n",
176
+ "importlib.reload(metric)\n",
177
+ "\n",
178
+ "vqa_evaluator = metric.VQAEvaluator()\n",
179
+ "aesthetic_evaluator = metric.AestheticEvaluator()"
180
+ ]
181
+ },
182
+ {
183
+ "cell_type": "code",
184
+ "execution_count": 11,
185
+ "metadata": {},
186
+ "outputs": [
187
+ {
188
+ "name": "stdout",
189
+ "output_type": "stream",
190
+ "text": [
191
+ "VQA Score: 0.9996758976500401\n",
192
+ "Aesthetic Score: 0.5749330520629883\n",
193
+ "Final Fidelity Score: 0.8709845773271212\n"
194
+ ]
195
+ }
196
+ ],
197
+ "source": [
198
+ "# score gpt4o generated images\n",
199
+ "import ast\n",
200
+ "import numpy as np\n",
201
+ "from PIL import Image\n",
202
+ "\n",
203
+ "# Load the first sample from descriptions.csv\n",
204
+ "descriptions_df = pd.read_csv('data/descriptions.csv')\n",
205
+ "first_description = descriptions_df.iloc[1]\n",
206
+ "\n",
207
+ "eval_df = pd.read_csv('data/eval.csv')\n",
208
+ "first_eval = eval_df.iloc[1]\n",
209
+ "\n",
210
+ "# Load the image\n",
211
+ "image_path = 'data/gray_coat.png' # Assuming the image is saved with this name\n",
212
+ "image = Image.open(image_path)\n",
213
+ "\n",
214
+ "# Prepare the inputs for scoring - need to parse the string representations\n",
215
+ "questions = ast.literal_eval(first_eval['question'])\n",
216
+ "choices = ast.literal_eval(first_eval['choices'])\n",
217
+ "answers = ast.literal_eval(first_eval['answer'])\n",
218
+ "\n",
219
+ "# Calculate VQA score - don't wrap in additional lists\n",
220
+ "vqa_score = vqa_evaluator.score(questions, choices, answers, image)\n",
221
+ "\n",
222
+ "# Calculate aesthetic score\n",
223
+ "aesthetic_score = aesthetic_evaluator.score(image)\n",
224
+ "\n",
225
+ "# Apply image processing as done in the metric.score function\n",
226
+ "image_processor = metric.ImageProcessor(image=image, seed=0).apply()\n",
227
+ "processed_image = image_processor.image.copy()\n",
228
+ "\n",
229
+ "# Calculate final fidelity score\n",
230
+ "instance_score = metric.harmonic_mean(vqa_score, aesthetic_score, beta=0.5)\n",
231
+ "\n",
232
+ "print(f\"VQA Score: {vqa_score}\")\n",
233
+ "print(f\"Aesthetic Score: {aesthetic_score}\")\n",
234
+ "print(f\"Final Fidelity Score: {instance_score}\")"
235
+ ]
236
+ }
237
+ ],
238
+ "metadata": {
239
+ "kernelspec": {
240
+ "display_name": "dwl",
241
+ "language": "python",
242
+ "name": "python3"
243
+ },
244
+ "language_info": {
245
+ "codemirror_mode": {
246
+ "name": "ipython",
247
+ "version": 3
248
+ },
249
+ "file_extension": ".py",
250
+ "mimetype": "text/x-python",
251
+ "name": "python",
252
+ "nbconvert_exporter": "python",
253
+ "pygments_lexer": "ipython3",
254
+ "version": "3.11.11"
255
+ }
256
+ },
257
+ "nbformat": 4,
258
+ "nbformat_minor": 2
259
+ }