hey
Problem Statement
Feature Extraction from Images
In this hackathon, the goal is to create a machine learning model that extracts entity values from images. This capability is crucial in fields like healthcare, e-commerce, and content moderation, where precise product information is vital. As digital marketplaces expand, many products lack detailed textual descriptions, making it essential to obtain key details directly from images. These images provide important information such as weight, volume, voltage, wattage, dimensions, and many more, which are critical for digital stores.
Data Description:
The dataset consists of the following columns:
index: A unique identifier (ID) for the data sample.
image_link: Public URL where the product image is available for download. Example link - https://m.media-amazon.com/images/I/71XfHPR36-L.jpg  To download images, use the download_images function from src/utils.py. See sample code in src/test.ipynb.
group_id: Category code of the product.
entity_name: Product entity name. For example, “item_weight”.
entity_value: Product entity value. For example, “34 gram”.
Note: For test.csv, you will not see the column entity_value as it is the target variable.
Output Format:
The output file should be a CSV with 2 columns:
index: The unique identifier (ID) of the data sample. Note that the index should match the test record index.
prediction: A string which should have the following format: “x unit” where x is a float number in standard formatting and unit is one of the allowed units (allowed units are mentioned in the Appendix). The two values should be concatenated and have a space between them.
For example: “2 gram”, “12.5 centimetre”, “2.56 ounce” are valid.
Invalid cases: “2 gms”, “60 ounce/1.7 kilogram”, “2.2e2 kilogram”, etc.
Note: Make sure to output a prediction for all indices. If no value is found in the image for any test sample, return an empty string, i.e., “”. If you have less/more number of output samples in the output file as compared to test.csv, your output won’t be evaluated.
File Descriptions:
Source Files:
src/sanity.py: Sanity checker to ensure that the final output file passes all formatting checks.
Note: The script will not check if fewer/more number of predictions are present compared to the test file. See sample code in src/test.ipynb.
src/utils.py: Contains helper functions for downloading images from the image_link.
src/constants.py: Contains the allowed units for each entity type.
sample_code.py: A sample dummy code that can generate an output file in the given format. Usage of this file is optional.
Dataset Files:
dataset/train.csv: Training file with labels (entity_value).
dataset/test.csv: Test file without output labels (entity_value). Generate predictions using your model/solution on this file's data and format the output file to match sample_test_out.csv (Refer to the "Output Format" section above).
dataset/sample_test.csv: Sample test input file.
dataset/sample_test_out.csv: Sample outputs for sample_test.csv. The output for test.csv must be formatted in the exact same way.
Note: The predictions in the file might not be correct.
Constraints:
You will be provided with a sample output file and a sanity checker file. Format your output to match the sample output file exactly and pass it through the sanity checker to ensure its validity.
Note: If the file does not pass through the sanity checker, it will not be evaluated. You should receive a message like Parsing successful for file: ...csv if the output file is correctly formatted.
You are given the list of allowed units in constants.py and also in the Appendix. Your outputs must be in these units. Predictions using any other units will be considered invalid during validation.

here's constants.py
entity_unit_map = {
    'width': {'centimetre', 'foot', 'inch', 'metre', 'millimetre', 'yard'},
    'depth': {'centimetre', 'foot', 'inch', 'metre', 'millimetre', 'yard'},
    'height': {'centimetre', 'foot', 'inch', 'metre', 'millimetre', 'yard'},
    'item_weight': {'gram',
        'kilogram',
        'microgram',
        'milligram',
        'ounce',
        'pound',
        'ton'},
    'maximum_weight_recommendation': {'gram',
        'kilogram',
        'microgram',
        'milligram',
        'ounce',
        'pound',
        'ton'},
    'voltage': {'kilovolt', 'millivolt', 'volt'},
    'wattage': {'kilowatt', 'watt'},
    'item_volume': {'centilitre',
        'cubic foot',
        'cubic inch',
        'cup',
        'decilitre',
        'fluid ounce',
        'gallon',
        'imperial gallon',
        'litre',
        'microlitre',
        'millilitre',
        'pint',
        'quart'}
}

allowed_units = {unit for entity in entity_unit_map for unit in entity_unit_map[entity]}

here's utils.py
import re
import constants
import os
import requests
import pandas as pd
import multiprocessing
import time
from time import time as timer
from tqdm import tqdm
import numpy as np
from pathlib import Path
from functools import partial
import requests
import urllib
from PIL import Image

def common_mistake(unit):
    if unit in constants.allowed_units:
        return unit
    if unit.replace('ter', 'tre') in constants.allowed_units:
        return unit.replace('ter', 'tre')
    if unit.replace('feet', 'foot') in constants.allowed_units:
        return unit.replace('feet', 'foot')
    return unit

def parse_string(s):
    s_stripped = "" if s==None or str(s)=='nan' else s.strip()
    if s_stripped == "":
        return None, None
    pattern = re.compile(r'^-?\d+(\.\d+)?\s+[a-zA-Z\s]+$')
    if not pattern.match(s_stripped):
        raise ValueError("Invalid format in {}".format(s))
    parts = s_stripped.split(maxsplit=1)
    number = float(parts[0])
    unit = common_mistake(parts[1])
    if unit not in constants.allowed_units:
        raise ValueError("Invalid unit [{}] found in {}. Allowed units: {}".format(
            unit, s, constants.allowed_units))
    return number, unit


def create_placeholder_image(image_save_path):
    try:
        placeholder_image = Image.new('RGB', (100, 100), color='black')
        placeholder_image.save(image_save_path)
    except Exception as e:
        return

def download_image(image_link, save_folder, retries=3, delay=3):
    if not isinstance(image_link, str):
        return

    filename = Path(image_link).name
    image_save_path = os.path.join(save_folder, filename)

    if os.path.exists(image_save_path):
        return

    for _ in range(retries):
        try:
            urllib.request.urlretrieve(image_link, image_save_path)
            return
        except:
            time.sleep(delay)
    
    create_placeholder_image(image_save_path) #Create a black placeholder image for invalid links/images

def download_images(image_links, download_folder, allow_multiprocessing=True):
    if not os.path.exists(download_folder):
        os.makedirs(download_folder)

    if allow_multiprocessing:
        download_image_partial = partial(
            download_image, save_folder=download_folder, retries=3, delay=3)

        with multiprocessing.Pool(64) as pool:
            list(tqdm(pool.imap(download_image_partial, image_links), total=len(image_links)))
            pool.close()
            pool.join()
    else:
        for image_link in tqdm(image_links, total=len(image_links)):
            download_image(image_link, save_folder=download_folder, retries=3, delay=3)
        

this is my train.csv
image_link,group_id,entity_name,entity_value
https://m.media-amazon.com/images/I/61I9XdN6OFL.jpg,748919,item_weight,500.0 gram
https://m.media-amazon.com/images/I/71gSRbyXmoL.jpg,916768,item_volume,1.0 cup
https://m.media-amazon.com/images/I/61BZ4zrjZXL.jpg,459516,item_weight,0.709 gram
https://m.media-amazon.com/images/I/612mrlqiI4L.jpg,459516,item_weight,0.709 gram
https://m.media-amazon.com/images/I/617Tl40LOXL.jpg,731432,item_weight,1400 milligram
https://m.media-amazon.com/images/I/61QsBSE7jgL.jpg,731432,item_weight,1400 milligram
https://m.media-amazon.com/images/I/81xsq6vf2qL.jpg,731432,item_weight,1400 milligram
https://m.media-amazon.com/images/I/71DiLRHeZdL.jpg,731432,item_weight,1400 milligram
https://m.media-amazon.com/images/I/91Cma3RzseL.jpg,731432,item_weight,1400 milligram
https://m.media-amazon.com/images/I/71jBLhmTNlL.jpg,731432,item_weight,1400 milligram
https://m.media-amazon.com/images/I/81N73b5khVL.jpg,149159,item_weight,30.0 kilogram
https://m.media-amazon.com/images/I/61oMj2iXOuL.jpg,308856,item_weight,10 kilogram to 15 kilogram

this is my test.csv
index,image_link,group_id,entity_name
0,https://m.media-amazon.com/images/I/110EibNyclL.jpg,156839,height
1,https://m.media-amazon.com/images/I/11TU2clswzL.jpg,792578,width
2,https://m.media-amazon.com/images/I/11TU2clswzL.jpg,792578,height
3,https://m.media-amazon.com/images/I/11TU2clswzL.jpg,792578,depth
4,https://m.media-amazon.com/images/I/11gHj8dhhrL.jpg,792578,depth
5,https://m.media-amazon.com/images/I/11gHj8dhhrL.jpg,792578,height
6,https://m.media-amazon.com/images/I/11gHj8dhhrL.jpg,792578,width
7,https://m.media-amazon.com/images/I/11lshEUmCrL.jpg,156839,height
8,https://m.media-amazon.com/images/I/21+i52HRW4L.jpg,478357,width
9,https://m.media-amazon.com/images/I/21-LmSmehZL.jpg,478357,height
10,https://m.media-amazon.com/images/I/213oP6n7jtL.jpg,953313,item_weight
11,https://m.media-amazon.com/images/I/213wY3gUsmL.jpg,276611,width
12,https://m.media-amazon.com/images/I/214CLs1oznL.jpg,648011,depth
13,https://m.media-amazon.com/images/I/214CLs1oznL.jpg,648011,height
14,https://m.media-amazon.com/images/I/214CLs1oznL.jpg,648011,width
15,https://m.media-amazon.com/images/I/216rjgJHAeL.jpg,279307,item_weight



this is how my output should be 
index,prediction
0,21.9 foot
1,10 foot
2,
3,289.52 kilovolt

ok so how do i go about this problem and find the best solution that finds the solution