-
PyFireCRESTin käyttö Python-skriptissä tai Jupyter Notebookissa
PyFireCRESTin käyttö Python-skriptissä tai Jupyter Notebookissa
Tällä sivulla annetaan esimerkki siitä, miten voit käyttää FireCRESTiä Roihun ja LUMIn käyttämiseen Python-skriptistä tai Jupyter Notebookista. Koulutamme luokittelijamallin Iris-aineistolla ja tuotamme sekaannusmatriisin. Pythonin ja sen käytön HPC-ympäristössä perustaidot oletetaan. Jos et ole varma näistä aiheista, katso sivu Pythonin käyttö CSC:n supertietokoneilla. Katso myös CSC FirecREST -dokumentaatio ja PyFirecREST-dokumentaatio. Voit ladata Python-notebookin, joka toteuttaa tämän ohjeen, ja seurata mukana sen avulla.
Tämä työnvuo mahdollistaa käsittelemättömän datasi helpon muokkaamisen notebookissa tai Python-skriptissä samalla, kun raskaat laskennat tehdään HPC-resursseilla. Näin käytät BU:ita vain raskaaseen laskentaan, et niihin osiin, jotka voit tehdä paikallisesti.
Käytämme tässä ohjeessa Roihua. Mahdolliset erot LUMIin mainitaan niiden tullessa vastaan.
Alkuvalmistelut
Asenna PyFireCREST ympäristöösi. Voit tehdä tämän komennolla pip install pyfirecrest. Sen jälkeen voit tuoda firecrestin
# Mandatory imports:
import firecrest as fc
# Whatever you need for your own code.
import jwt
import pandas as pd
import os
import time
# Set constants:
RAW_DATA_PATH = "~/Downloads/iris.csv"
ROIHU_PROJ_DIR = "/scratch/project_1234567/<username>/jupyter-dir/"
OUTPUT_FILENAME = "confusion_matrix.png"
FIRECREST_URL = "https://api.roihu.csc.fi/v1"
ACCOUNT = "project_1234567"
Hae henkilökohtainen käyttöoikeustunnisteesi. Ohjeet tähän ja tarkka API-päätepiste löytyvät sivulta Yhdistäminen Roihun FirecREST HPC APIin ja LUMIn osalta LUMIn dokumentaatiosta.
Warning
FirecREST HPC APIa varten myönnetyt käyttöoikeustunnisteet sallivat tunnisteen haltijan olla vuorovaikutuksessa Slurm-töiden kanssa sekä lukea, muokata ja siirtää dataa sinun käyttöoikeuksillasi. Älä jaa käyttöoikeustunnistettasi kenellekään.
Tässä esimerkissä tallennamme sen työtilan .env-tiedostoon ja lataamme sen dotenv-kirjastolla. Voimme sitten lisätä .env-tiedoston gitignoreen ja tehdä yhteistyötä muiden kanssa paljastamatta tunnistetta.
Ennen kuin voimme kutsua FireCRESTiä, meidän on toteutettava luokka, jossa on get_access_token()-metodi. Jos käytät robottitunnusta, voit käyttää sisäänrakennettua valtuutusluokkaa ClientCredentialsAuth.
Esimerkkitoteutus valtuutusluokasta löytyy Python SDK:sta.
class TokenAuth:
def __init__(self):
pass
# Use PyJWT to decode the token and verify expiration time.
# Return False if decoding fails (input is not valid JWT) or if the token has expired
def _is_token_valid(self, token: str) -> bool:
try:
payload = jwt.decode(token, options={"verify_signature": False, "verify_exp": False, "verify_aud": False})
return time.time() <= payload["exp"]
except Exception:
return False
# A PyFirecREST Authorization object is required to have method get_access_token(),
# which, when called, will return a valid JWT access token.
def get_access_token(self):
token = os.getenv('FIRECREST_TOKEN', None)
if not token:
raise RuntimeError("Environment variable FIRECREST_TOKEN is not defined.")
if not self._is_token_valid(token):
raise RuntimeError("Token is invalid or has expired.")
return token
Ennen kuin voimme ladata tiedoston, meidän on alustettava Firecrest-yhteys API-URL-osoitteella ja valtuutusluokalla TokenAuth().
Kirjaston täydellisen dokumentaation voit katsoa täältä: PyfirecREST-dokumentaatio.
Datan esikäsittely
Lataa datasi ja tee sille kaikki tarvitsemasi käsittelyt. Tässä käytämme Iris-aineistoa ja suodatamme poikkeavia havaintoja.
Tee esikäsittelysi ja/tai piirremuokkauksesi.
df = df.dropna()
q_low = df["sepal_length"].quantile(0.01)
q_high = df["sepal_length"].quantile(0.99)
df_filtered = df[(df["sepal_length"] < q_high) & (df["sepal_length"] > q_low)]
df_filtered = df_filtered.drop(columns="sepal_width")
print(df_filtered.head())
print(f"Original row count: {len(df)}, filtered row count: {len(df_filtered)}")
Nyt olemme valmiita kouluttamaan mallimme. Tallennamme käsittelemämme datan csv-tiedostoon.
Tiedostojen lataaminen Roihuun
Nyt lataamme tiedoston käyttäen firecrest.upload()-metodia, mutta varmistamme ensin hakemiston olemassaolon komennolla firecrest.mkdir().
Kun käytetään firecrest-metodeja, kaikki niistä vaativat syötteenä system_name. Tämä erottaa eri noodityypit, "cpu" ja "gpu". Koska Roihu käyttää jaettua tiedostojärjestelmää, ainoa komento, johon tällä on vaikutusta, on firecrest.submit().
Jos käytät LUMIa, käytä kaikissa firecrest-komennoissa system_name="lumi".
Jos ladattava tiedosto on suurempi kuin firecrest.MAX_DIRECT_UPLOAD_SIZE ~ 1 MB, se ladataan eräajona. Lisää account-parametriin projekti, jonka jäsen olet, EI käyttäjätiliäsi Roihussa. Ilman account-parametria lataus epäonnistuu.
Local_file-polun tulee olla absoluuttinen polku.
filename_on_roihu = "training_data.csv"
upload = firecrest.upload(system_name="cpu", local_file=upload_file, directory=ROIHU_PROJ_DIR, filename=filename_on_roihu, account=ACCOUNT)
# Check if upload is done as a batch job or not:
if upload != None:
print("Upload as a batch job, may take a while.")
# Wait for job to finish
upload.wait_for_transfer_job()
print(f"Upload complete for file {upload_file}.")
Työn lähettäminen
Note
Ympäristömuuttuja CSC_ENV_INIT_NON_INTERACTIVE=yes on välitettävä Slurm-työhön,
muuten ympäristöä ei alusteta oikein, eikä muun muassa moduulit toimi oikein.
Ympäristömuuttujien välittämiseen käytämme sanakirjaa. CSC_ENV_INIT_NON_INTERACTIVE=yes-muuttujan lisäksi välitämme muuttujat OUTPUT_FILENAME ja DATA_FILE, joita voimme sitten käyttää Slurm-skriptissä.
env_vars = dict()
env_vars["CSC_ENV_INIT_NON_INTERACTIVE"] = "yes"
env_vars["OUTPUT_FILENAME"] = OUTPUT_FILENAME
env_vars["DATA_FILE"] = filename_on_roihu
Lähettääksemme työn laskentanoodeille tarvitsemme Slurm-skriptin aivan kuten lähettäisimme sen Roihussa. Katso ohjeet sivulta Roihun dokumentaatio tai LUMIn dokumentaatio.
Voit kirjoittaa skriptin paikallisesti ja ladata sen Roihuun samalla tavalla kuin datan, tai voit antaa syötteenä paikallisen Slurm-skriptin polun. Käytämme jälkimmäistä vaihtoehtoa.
Skripti tallennetaan polkuun ./iris_slurm_script.sh.
Jos käytät LUMIa, et voi käyttää täsmälleen tätä skriptiä, koska LUMIssa ei ole python-data-moduulia. Jos haluat seurata tämän ohjeen loppuosaa, voit korvata Slurm-skriptin rivin module load python-data seuraavalla:
module load cray-python
python3 -m venv .venv
source .venv/bin/activate
pip install scikit-learn
pip install matplotlib
pip install pandas
Muista lukea LUMIn dokumentaatiosta Python-pakettien asentamisesta.
shebang
Sinun on käytettävä eräajotiedoston alussa shebang-riviä #!/bin/bash -l, jotta
laskentaympäristö, kuten moduulijärjestelmä, toimii.
#!/bin/bash -l
#SBATCH --job-name=firecrest_test_job
#SBATCH --partition=small
#SBATCH --account=project_1234567
#SBATCH --cpus-per-task=1
#SBATCH --mem=2G
#SBATCH --time=00:02:00
#SBATCH --output=bb_test_cpu_%j.out
#SBATCH --error=bb_test_cpu_%j.err
module load python-data
python3 - << 'EOF'
import pandas as pd
import matplotlib.pyplot as plt
import os
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
# Read the data into a dataframe:
df = pd.read_csv(os.getenv("DATA_FILE"))
# Separate features and label
X = df.drop(columns="species")
y = df["species"]
# Split into train and test set
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Fit DecisionTree model
clf = DecisionTreeClassifier(random_state=42)
clf.fit(X_train, y_train)
# Predict on test set
y_pred = clf.predict(X_test)
# Create confusion matrix, save it to file.
cm = confusion_matrix(y_test, y_pred)
disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=clf.classes_)
disp.plot(cmap=plt.cm.Blues)
plt.title("Confusion Matrix")
plt.savefig(os.getenv("OUTPUT_FILENAME"), format="png")
EOF
Koska ajettava Python-skripti on suhteellisen lyhyt, Slurm-skriptissä koodi on suoraan sisällytettynä, mutta voisimme myös luoda run_classifier.py-tiedoston, ladata sen Roihuun ja kutsua sitä Slurm-skriptistä. Koska käytämme scikit-learn- ja pandas-kirjastoja, meidän on ladattava python-data-moduuli skriptin alussa.
Python lukee lataamamme esikäsitellyn datan, jakaa sen opetus- ja testijoukkoihin, kouluttaa päätöspuuluokittelijan ja luo sekaannusmatriisin luokittelijan suorituskyvystä testijoukossa.
Nyt lähetämme työn komennolla firecrest.submit. Syötteet ovat:
- system_name: Pyydätkö CPU- vai GPU-osiota?
- working_dir: Työn työhakemisto.
- script_local_path: polku (täysi tai suhteellinen) koneellasi olevaan Slurm-skriptiin. Valinnainen
- script_remote_path: polku Roihussa olevaan Slurm-skriptiin. Valinnainen
- env_vars: ympäristömuuttujien sanakirja, jonka on sisällettävä vähintään
CSC_ENV_INIT_NON_INTERACTIVE=yes
job = firecrest.submit(system_name="cpu", working_dir=ROIHU_PROJ_DIR, script_local_path="iris_slurm_script.sh", env_vars=env_vars)
jobid = job["jobId"]
Tulosten lataaminen
Odota työn valmistumista komennolla firecrest.wait_for_job(). Kun työ on valmis, voimme ladata tulokset, jotka voivat olla mikä tahansa tiedosto. Tässä tapauksessa kyseessä on sekaannusmatriisin png-kuva. Huomioitavat wait_for_job-parametrit ovat:
- timeout: Sekuntimäärä, jonka jälkeen työ peruutetaan.
- not_found_timeout: Sekuntimäärä, jonka jälkeen wait_for_job nostaa virheen, mutta ei peruuta itse työtä.
- tiedostoille > ~1 MB account-parametrin on oltava projektin nimi.
Ladattaessa target_path voi olla mikä tahansa polku paikallisella koneellasi, kunhan se sisältää tiedoston. Se voi olla suhteellinen polku. Käytämme arvoa OUTPUT_FILENAME = "confusion_matrix.png", joten tiedosto ladataan nykyiseen työhakemistoomme.
download = firecrest.download(system_name="cpu", source_path=os.path.join(ROIHU_PROJ_DIR, OUTPUT_FILENAME), target_path=OUTPUT_FILENAME, account=ACCOUNT)
if download != None:
print("Download is done as a batch job, waiting for it to finish.")
download.wait_for_transfer_job()
print(f"Results downloaded successfully to {OUTPUT_FILENAME}.")
Nyt voit analysoida tuloksia paikallisesti millä tahansa käytettävissäsi olevilla työkaluilla.