Mes dhjetëra artikujve mbi ChatGPT, nuk kam hasur ende në një përpjekje për të përdorur këtë model të madh gjuhësorpër të gjeneruar drejtpërdrejt parashikime. U kërkua shumë herë të krijonte një kod përkatës për ta bërë këtë, por në teori mund të ishte edhe në gjendje të prodhonte një parashikim të arsyeshëm. Pa u zgjatur më shumë, le të bëjmë një eksperiment dhe të ushqejmë modelin ChatGPT me të dhëna të papërpunuara të serive kohore.

Këshilla bazë

Jini të saktë në kërkesat tuaja

Me fjalë të tjera, mos lini vend për hamendje. Përndryshe, ChatGPT mund të p.sh. ktheni përgjigjet në shumë formate të ndryshme ose përpiquni të largoheni me justifikime si "Unë jam vetëm një model gjuhe" etj. Ky është mësimi më i rëndësishëm që duhet të mësoni nëse do të bëheni një inxhinier i shpejtë em>. Për më shumë informacion, ju lutemi njihuni me këtë kurs të shkurtër (por të dobishëm) nga DeepLearning.AI.

Mos harroni kufizimin e gjatësisë hyrëse/dalëse të modelit

Gjëja tjetër e rëndësishme është të mbani mend kufizimin e ChatGPT në lidhje me gjatësinë hyrëse/dalëse. Ai bazohet në numrin e të ashtuquajturave shenja, të cilat nuk mund të interpretohen thjesht si karaktere ose fjali. Si kërkesa dhe përfundimi krijojnë një kontekst, gjatësia e të cilit nuk mund të kalojë një numër të caktuar të deklaruar në "dokumentacion" (për shembull, 4096 shenja për gpt-3.5-turbo). Mënyra më e lehtë për të numëruar argumentet është të përdorni "tokenizuesin për GPT-3" nga OpenAI.

Ngrohje

Mendoj se grupi i të dhënave për pasagjerët e linjës ajrore, i njohur zakonisht nga praktikuesit e parashikimit të serive kohore, është një pikënisje e mirë për këtë eksperiment. Le t'i marrim këto të dhëna duke përdorur paketën sktime.

from sktime.datasets import load_airline
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['figure.figsize'] = [20, 10]

# Loading data
air_passengers = load_airline()

# Plotting
sns.set_theme()
air_passengers.plot(title='Airline passengers 1949-1960')
plt.show()

Pastaj, le ta ndajmë duke përdorur, të themi, dy vitet e fundit si periudhë testimi dhe të gjitha të tjerat si periudhë trajnimi.

y_train = air_passengers[air_passengers.index < '1959-01']
y_test  = air_passengers[air_passengers.index >= '1959-01']

Më pas, ne krijojmë një funksion që thërret ChatGPT API në një mënyrë të zgjuar për të marrë parashikimin në formatin JSON. Në hapin tjetër, ne përpiqemi ta analizojmë atë dhe ta transformojmë fjalorin e daljes në një DataFrame panda. Ne duhet të përdorim bllokun "provo-përveç", sepse në disa raste ChatGPT mund të kthejë përgjigjen në një format të papritur. Në një situatë të tillë, ne trajtojmë përjashtimin e analizës JSON dhe kthejmë përgjigjen e papërpunuar ChatGPT si rezultat.

import openai
import os
import json

# You have to generate your OpenAI API key first and assign it to
# an environmental variable
# For Linux, it looks as follows:
# export OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
openai.api_key = os.getenv('OPENAI_API_KEY')


def chat_gpt_forecast(data, horizon, 
                      time_idx='Period', 
                      forecast_col = 'Forecast',
                      model="gpt-3.5-turbo",
                      verbose=False):
    
    prompt = f""" 
    Given the dataset delimited by the triple backticks, 
    forecast next {horizon} values of the time series. 

    Return the answer in JSON format, containing two keys: '{time_idx}' 
    and '{forecast_col}', and list of values assigned to them. 
    Return only the forecasts, not the Python code.

    ``` {data.to_string()}``` 
    """
    
    if verbose:
      print(prompt)
    
    messages = [{"role": "user", "content": prompt}]
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=0, 
    )
    
    output = response.choices[0].message["content"]
    
    try:
        json_object = json.loads(output)
        df = pd.DataFrame(json_object)
        df[time_idx] = df[time_idx].astype(data.index.dtype)
    except:
        df = output
        print(output)
    
    return df

Le të krijojmë disa parashikime dhe të kontrollojmë se sa të sakta janë ato.

gpt_forecast = chat_gpt_forecast(y_train, horizon)
y = air_passengers.reset_index()
y.merge(gpt_forecast, how='outer') \
  .plot(x='Period', y=['Number of airline passengers', 'Forecast'])

Jo keq. Gjithsesi, duhet të kujtojmë se ishte vetëm një ngrohje. Për shkak të popullaritetit të tij, ky grup të dhënash nuk është më i miri për të testuar aftësinë e ChatGPT për "arsyetim". Testi i vërtetë është duke përdorur modelin mbi të dhënat që nuk mund t'i shihte më parë. Për të qenë të sigurt për këtë, ne do të krijojmë një seri kohore nga e para.

Të dhënat e lodrave

Unë dola me një grup të dhënash, i cili imiton sjelljen e shitjeve të verërave të gazuara gjatë disa viteve. Për shkak të kufizimeve që kemi përmendur tashmë, ne nuk mund ta ushqejmë modelin me një grup të dhënash që është shumë i gjatë, kështu që zgjedhja e të dhënave mujore duket të jetë alternativa më e mirë. Për studimin supozojmë se:

  • vera e gazuar shitet më mirë gjatë verës
  • kulmi i shitjeve bie në muajin e fundit të vitit (në prag të Vitit të Ri)
  • ka një prirje lineare, rritëse në seritë kohore
import numpy as np
from typing import Tuple, List

def get_champagne(years: Tuple[int, int] = (2018, 2023),
                  normal_days: dict =  {'n': 1000, 'p': 0.02},
                  weekdays: dict = {4: {'n': 1800, 'p': 0.03},
                                    5: {'n': 2000, 'p': 0.05}},
                  special_events: dict = {(29, 12): {'n': 1500, 'p': 0.1},
                                          (30, 12): {'n': 2000, 'p': 0.2},
                                          (31, 12): {'n': 2000, 'p': 0.7}},
                 trend=.01,
                 seas_months=[6, 7, 8],
                 seas_coef=1.2):

    """Model for sparkling wine demand"""
    
    df = pd.DataFrame({
        'date': pd.date_range(f'{years[0]}-01-01', f'{years[1]}-12-31')    
    })
    
    df['weekday'] =  df['date'].dt.weekday
    df['monthday'] =  df['date'].dt.day
    df['month'] =  df['date'].dt.month
    df['week'] =  df['date'].dt.strftime('%U')
    df['year'] =  df['date'].dt.year
    
    normal_days_amount = np.random.binomial(**normal_days, size=len(df))
    df['amount'] = normal_days_amount
    
    # Trend
    df['amount'] += np.array(df.index.values) * trend
    df['amount'] = df['amount'].astype(int)
    
    if weekdays:
        for wd, params in weekdays.items():
            mask = df.weekday == wd
            df.loc[mask, 'amount'] = np.random.binomial(**params, size=mask.sum())
    
    if special_events:
        for d, params in special_events.items():
            mask = (df.monthday == d[0]) & (df.month == d[1]) 
            df.loc[mask, 'amount'] = np.random.binomial(**params, size=mask.sum())
            col_name = f'special_event_{d[0]}_{d[1]}'
            df[col_name] = 0
            df.loc[mask, col_name] = 1
    
    # Aggregation
    df = df[['year', 'month', 'amount']]
    df = df.groupby(['year', 'month']).sum()
    
    # Create period date
    period = df\
        .reset_index() \
        .apply(lambda x: pd.Period(f"{x['year']}-{x['month']}", freq='M'), axis=1)
    
    df['period'] = period.tolist()
    df = df.reset_index()
    
    # Adding seasonality
    df.loc[df.month.isin(seas_months), 'amount'] *= seas_coef
    df['amount'] = df['amount'].astype(int)
    
    return df[['period', 'amount']]

Nëse ju duket shumë e ndërlikuar kjo pjesë e kodit, mund ta rishkruani sipas dëshirës. Unë miratova fragmentin e mësipërm nga një eksperiment tjetër që bëra, kjo është arsyeja që unë gjeneroj vëzhgimet e përditshme në vend që të krijoj direkt të dhëna mujore.

START_YEAR = 2015
END_YEAR = 2023
SPLIT_DATE = '2022-12-31'

np.random.seed(7)

data = get_champagne(years=(START_YEAR, END_YEAR),
                    special_events={(31, 12): {'n': 2000, 'p': 0.7}})
data.plot(x='period', y='amount')

Së fundi, i kërkojmë ChatGPT të gjenerojë parashikimin për vitin 2023, duke pasur parasysh të dhënat midis 2015-2022.

train_data = data.head(-12)
test_data = data.tail(12)

# Forecasting
champagne_chatgpt = \
  chat_gpt_forecast(
      data         = train_data.set_index('period'), 
      horizon      = 12,
      time_idx     = 'period',
      forecast_col = 'forecast'
)

# Plotting 
data \
    .merge(champagne_chatgpt, on='period', how='outer') \
    .plot(x='period', y=['amount', 'forecast'])

Për të qenë i sinqertë, jam i habitur, sa i mirë është ky parashikim. Duket se ChatGPT ka një kuptim themelor të sezonalitetit dhe trendit. Për momentin, LLM-të nuk janë ende mjetet më të mira për të parashikuar seritë kohore, qoftë edhe vetëm për shkak të kufizimeve të madhësisë së tyre hyrëse/dalëse. Një tjetër dobësi e mundshme e përdorimit të LLM-ve për parashikimin e serive kohore është paaftësia për të parë nën kapak të modelit, për të shpjeguar se çfarë lloj matematike fshihet pas gjithë kësaj. E kam fjalën për rregullat matematikore të mësuara nga ChatGPT. Gjithsesi, eksperimenti im tregon, se ndoshta një ditë LLM-të do të përdoren për qëllime të tilla. Dhe, kush e di, nëse nuk është pasnesër.