mlco2 / codecarbon

Track emissions from Compute and recommend ways to reduce their impact on the environment.
https://mlco2.github.io/codecarbon
MIT License
1.17k stars 177 forks source link

Is it right that the Carbon Intensity of Solar, Wind, ... is ignored in your calculations? #673

Closed headscott closed 2 weeks ago

headscott commented 2 months ago

Description

I am about to write a paper about sustainability of AI for my university. Therefore I wanted to know what Electricity mix (Percentages of Coal, Petroleum, Natural Gas, Solar, ...) your code is guessing and how it gets the values/where are the guessed values from?

Where can I get more current information about the german energy mix/Where did you get it from?

What I Did

I saw in /codecarbon/core/emissions.py that there is a function called _region_energy_mix_to_emissions_rate which only uses coal, petroleum and natural gas. But on your website CodeCarbon there is also mentioned emissions for Solar, Wind, ...

benoit-cty commented 2 months ago

Hello,

The function you mention is only used in the case of an error DataSourceException, which is not supposed to happen anymore.

Our data came from our_world_in_data and you can see them in the file https://github.com/mlco2/codecarbon/blob/master/codecarbon/data/private_infra/global_energy_mix.json

We could also use ElectricityMaps to get the energy mix in realtime.

Let us know when your paper is out !

headscott commented 2 months ago

Is there a way for me to do something like get_regional_energy_mix(ISO_Code, Region) and get the same results that you used to calculate the CO2eq of the power consumption? If so, what should I do?

I tried this code, but it didn't work:

from codecarbon.external.geography import GeoMetadata
from codecarbon.input import DataSourceException
from codecarbon import EmissionsTracker

def get_my_energy_mix():
    # create EmissionTracker Instance
    tracker = EmissionsTracker()

    # define GeoMetadata for your region
    geo = GeoMetadata(
        country_iso_code,
        country_name,
        region,
        latitude,
        longitude
    )

    try:
        country_emissions_data = tracker._data_source.get_country_emissions_data(
            geo.country_iso_code.lower()
        )

        if geo.region not in country_emissions_data:
            # TODO: Deal with missing data, default to something
            raise ValueError(
                f"Region: {geo.region} not found for Country "
                + f" with ISO CODE: {geo.country_iso_code}"
            )

        print("Energy Mix for country:", country_emissions_data)

    except DataSourceException:
        # This country has regional data at the energy mix level,
        # not the emissions level

        try:
            country_energy_mix_data = tracker._data_source.get_global_energy_mix_data()
            if geo.region in country_energy_mix_data:
                region_energy_mix_data = country_energy_mix_data[geo.region]
                print("Energy Mix for region:", region_energy_mix_data)
            else:
                print(f"Energy mix-Data for {geo.region} is missing.")
        except KeyError as error:
            print("Error: Data not available.", error)

My paper will be in german btw

benoit-cty commented 2 months ago

Hello, You can do :

from codecarbon.input import DataSource
DataSource().get_global_energy_mix_data()["DEU"]
{
  "biofuel_TWh": 46.02,
  "carbon_intensity": 380.95,
  "coal_TWh": 135.35,
  "country_name": "Germany",
  "fossil_TWh": 231.48,
  "gas_TWh": 76,
  "hydroelectricity_TWh": 19.48,
  "iso_code": "DEU",
  "low_carbon_TWh": 273.31,
  "nuclear_TWh": 8.75,
  "oil_TWh": 20.13,
  "other_renewable_TWh": 46.23,
  "other_renewable_exc_biofuel_TWh": 0.21,
  "per_capita_Wh": 6060.295,
  "renewables_TWh": 264.56,
  "solar_TWh": 61.56,
  "total_TWh": 504.78999999999996,
  "wind_TWh": 137.29,
  "year": 2023
}

If you what to use realtime data, look at CO2 Signal in CodeCarbon as it was the previous name of ElectricityMaps API.

Even if it's in German it's always nice to see where and why CodeCarbon is used.

headscott commented 2 months ago

Okay thank you, this helped me. But I still have a problem:

this is the total energy consumption of one of my AI training runs: 5.4478812927977245kWh this is the calculated emissions in kgCO2: 2.0995535235500222

if I use the 380.95 carbon intensity, I get: 5.4478812927977245 * 380.95 = 2.07537037849129315kg so its a bit less. I've got version 2.5.0 btw.

And where do these 380.95 come from?

oil 20.13 -> 3.9878% of total Energy coal 135.35 -> 26.8131% gas 76 -> 15.0558% -> total fossil TWh: 231.48 --> 45.8567%

solar 61.56 -> 12.1952% wind 137.29 -> 27.1974% hydro 19.48 -> 3.859% biofuel 46.02 -> 9.1167% -> total renewable 264.56 -> 52.4099% nuclear 8.75 -> 1.7334% total 504.79

CO2eq = 0.268131 995 + 0.039878 816 + 0.150558 743 + 0.03859 26 + 0.017334 29 + 0.121952 48 + 0.271974 * 26 = 425.626433 (I am using the formula from CodeCarbon Methodology). And there is even the value for Geothermal missing.

But even with this value, I get 5.4478812927977245 * 425.626433 = 2.318766kg CO2

If I calculate it backwards, the CO2eq should be: 5,4478812927977245 * CO2eq = 2,0995535235500222 ==> CO2eq = 385.3889

So is it an older energy mix used for that caluclation? Which would it be then, and how can I get the mix (like 10% Coal, 12% Solar, ...)?

UPDATE:

If I run your code, I get:

{ 'biofuel_TWh': 41.51, 'carbon_intensity': 385.389, 'coal_TWh': 178.94, 'country_name': 'Germany', 'fossil_TWh': 280.96, 'gas_TWh': 79.8, 'hydroelectricity_TWh': 17.06, 'iso_code': 'DEU', 'low_carbon_TWh': 279.59, 'nuclear_TWh': 35.86, 'oil_TWh': 22.22, 'other_renewable_TWh': 41.75, 'other_renewable_exc_biofuel_TWh': 0.24, 'per_capita_Wh': 6723.654, 'renewables_TWh': 243.73, 'solar_TWh': 60.01, 'total_TWh': 560.55, 'wind_TWh': 124.91, 'year': 2022 }

and 385.389 should actually be correct for the calculation. But I still don't know how 385.389 is calculated with this energy mix

benoit-cty commented 1 month ago

'carbon_intensity': 385.389, is not computed, it came directly from Our World in Data, here is what we do to build the dataset : https://github.com/mlco2/codecarbon/blob/master/codecarbon/data/private_infra/our_world_in_data.ipynb

headscott commented 1 month ago

So, the computation formular on the mentioned website is nowhere used in your code?

benoit-cty commented 1 month ago

Yes, it was computed before, but now we read directly the carbon_intensity as it is now provided by Our World in Data.

headscott commented 1 month ago

okay thanks

headscott commented 1 month ago

Wait, when I look at the Website OurWorldinData, it says:

Germany,DEU,2022,420.05743
Germany,DEU,2023,380.95047

so for the newest version, after mine (2.5.0), it should be correct using 380.95 for 2023. But my version said

'carbon_intensity': 385.389

for 2022, as you mentioned too. So it's different from what the website says currently. Or did the values of 2022 change this year on their site?

benoit-cty commented 3 weeks ago

Thanks for reporting this, we will have a look in https://github.com/mlco2/codecarbon/pull/674

benoit-cty commented 2 weeks ago

Hello, I take a look at the German numbers and yes, there has been an update to OurWorldInData, as now we did find 380.95 as carbon intensity for 2023. This will be updated in the next 2.8.0 release.

headscott commented 2 weeks ago

And maybe you should also update the CodeCarbon Metology Website, and say that you don't calculate it in the code, but the calculation shows how it could be done. Or maybe update the calculation so that it matches the actual values from OurWorldInData?

benoit-cty commented 1 week ago

Thanks, what do you think of https://github.com/mlco2/codecarbon/pull/712/commits/bb05eaaacf9e96e1e094118c4db94c3aac1bb83b ?

headscott commented 1 week ago

Sounds good. Thanks