Tại sao có sự khác biệt giữa dự đoán trên bộ Xác thực và Bộ kiểm tra?


8

Tôi có một mô hình XGBoost đang cố gắng dự đoán liệu một loại tiền tệ sẽ tăng hay giảm trong giai đoạn tiếp theo (5 phút). Tôi có một bộ dữ liệu từ năm 2004 đến 2018. Tôi chia dữ liệu ngẫu nhiên thành 95% đào tạo và xác thực 5% và độ chính xác trên bộ Xác thực lên tới 55%. Sau đó, khi tôi sử dụng mô hình trên Bộ kiểm tra mới (dữ liệu từ năm 2019), độ chính xác giảm xuống dưới 51%.

Ai đó có thể giải thích tại sao điều đó có thể được?

Ý tôi là, tôi cho rằng mô hình đã không "nhìn thấy" (được đào tạo) dữ liệu xác nhận nữa so với dữ liệu thử nghiệm để nó thực sự có thể bị thừa?

Tôi đã đính kèm một mô hình đơn giản dưới đây để minh họa. Cái đó cho 54% trên bộ xác nhận nhưng chỉ 50,9% cho bộ thử nghiệm .

Cảm ơn vì sự giúp đỡ!

NB Một lý thuyết tôi đã có là, vì một số tính năng dựa trên dữ liệu lịch sử (ví dụ: trung bình di chuyển), nó có thể bị rò rỉ dữ liệu. Sau đó, tôi đã cố gắng khắc phục điều đó bằng cách chỉ dữ liệu mẫu không phải là một phần của việc tạo trung bình di chuyển. Ví dụ: nếu có trung bình di chuyển 3 kỳ thì tôi không lấy mẫu / sử dụng các hàng dữ liệu từ 2 giai đoạn trở lại. Điều đó đã không thay đổi bất cứ điều gì vì vậy nó không có trong mô hình dưới đây.

NB2 Mô hình dưới đây là phiên bản đơn giản của những gì tôi sử dụng. Lý do cho một bộ xác nhận cho tôi là vì tôi sử dụng thuật toán di truyền để điều chỉnh siêu tham số nhưng tất cả những gì được loại bỏ ở đây cho rõ ràng.

import pandas as pd
import talib as ta
from sklearn.utils import shuffle
pd.options.mode.chained_assignment = None
from sklearn.metrics import accuracy_score

# ## TRAINING AND VALIDATING
# ### Read in data
input_data_file = 'EURUSDM5_2004-2018_cleaned.csv'   # For train and validation
df = pd.read_csv(input_data_file)

# ### Generate features
#######################
# SET TARGET
#######################
df['target'] = df['Close'].shift(-1)>df['Close']       # target is binary, i.e. either up or down next period

#######################
# DEFINE FEATURES
#######################
df['rsi'] = ta.RSI(df['Close'], 14) 

# ### Treat the data
#######################
# FIND AND MAKE CATEGORICAL VARAIBLES AND DO ONE-HOT ENCODING
#######################
for col in df.drop('target',axis=1).columns:     # Crude way of defining variables with few unique variants as categorical
    if df[col].nunique() < 25:
        df[col] = pd.Categorical(df[col])

cats = df.select_dtypes(include='category')     # Do one-hot encoding for the categorical variables
for cat_col in cats:
    df = pd.concat([df,pd.get_dummies(df[cat_col], prefix=cat_col,dummy_na=False)],axis=1).drop([cat_col],axis=1)

uints = df.select_dtypes(include='uint8')
for col in uints.columns:                   # Variables from the one-hot encoding is not created as categoricals so do it here
    df[col] = df[col].astype('category')

#######################
# REMOVE ROWS WITH NO TRADES
#######################
df = df[df['Volume']>0]

#######################
# BALANCE NUMBER OF UP/DOWN IN TARGET SO THE MODEL CANNOT SIMPLY CHOOSE ONE AND BE SUCCESSFUL THAT WAY
#######################
df_true = df[df['target']==True]
df_false = df[df['target']==False]

len_true = len(df_true)
len_false = len(df_false)
rows = min(len_true,len_false)

df_true = df_true.head(rows)
df_false = df_false.head(rows)
df = pd.concat([df_true,df_false],ignore_index=True)
df = shuffle(df)
df.dropna(axis=0, how='any', inplace=True)

# ### Split data
df = shuffle(df)
split = int(0.95*len(df))

train_set = df.iloc[0:split]
val_set = df.iloc[split:-1]

# ### Generate X,y
X_train = train_set[train_set.columns.difference(['target', 'Datetime'])]
y_train = train_set['target']

X_val = val_set[val_set.columns.difference(['target', 'Datetime'])]
y_val = val_set['target']

# ### Scale
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()

cont = X_train.select_dtypes(exclude='category')                   # Find columns with continous (not categorical) variables
X_train[cont.columns] = sc.fit_transform(X_train[cont.columns])    # Fit and transform

cont = X_val.select_dtypes(exclude='category')                     # Find columns with continous (not categorical) variables
X_val[cont.columns] = sc.transform(X_val[cont.columns])            # Transform

cats = X_train.select_dtypes(include='category')
for col in cats.columns:
    X_train[col] = X_train[col].astype('uint8')

cats = X_val.select_dtypes(include='category')
for col in cats.columns:
    X_val[col] = X_val[col].astype('uint8')


# ## MODEL
from xgboost import XGBClassifier
model = XGBClassifier()
model.fit(X_train, y_train)

predictions = model.predict(X_val)
acc = 100*accuracy_score(y_val, predictions)
print('{0:0.1f}%'.format(acc))

# # TESTING
input_data_file = 'EURUSDM5_2019_cleaned.csv'   # For testing
df = pd.read_csv(input_data_file)

#######################
# SET TARGET
#######################
df['target'] = df['Close'].shift(-1)>df['Close']       # target is binary, i.e. either up or down next period
#######################
# DEFINE FEATURES
#######################
df['rsi'] = ta.RSI(df['Close'], 14)

#######################
# FIND AND MAKE CATEGORICAL VARAIBLES AND DO ONE-HOT ENCODING
#######################
for col in df.drop('target',axis=1).columns:     # Crude way of defining variables with few unique variants as categorical
    if df[col].nunique() < 25:
        df[col] = pd.Categorical(df[col])

cats = df.select_dtypes(include='category')     # Do one-hot encoding for the categorical variables
for cat_col in cats:
    df = pd.concat([df,pd.get_dummies(df[cat_col], prefix=cat_col,dummy_na=False)],axis=1).drop([cat_col],axis=1)

uints = df.select_dtypes(include='uint8')
for col in uints.columns:                   # Variables from the one-hot encoding is not created as categoricals so do it here
    df[col] = df[col].astype('category')

#######################
# REMOVE ROWS WITH NO TRADES
#######################
df = df[df['Volume']>0]
df.dropna(axis=0, how='any', inplace=True)

X_test = df[df.columns.difference(['target', 'Datetime'])]
y_test = df['target']

cont = X_test.select_dtypes(exclude='category')                     # Find columns with continous (not categorical) variables
X_test[cont.columns] = sc.transform(X_test[cont.columns])            # Transform

cats = X_test.select_dtypes(include='category')
for col in cats.columns:
    X_test[col] = X_test[col].astype('uint8')

predictions = model.predict(X_test)
acc = 100*accuracy_score(y_test, predictions)
print('{0:0.1f}%'.format(acc))

Câu trả lời:


6

Sự khác biệt duy nhất xuất hiện là dữ liệu. Có thể bộ kiểm tra (là dữ liệu mới nhất) khác một chút so với bộ kiểm tra / xác thực và dẫn đến hiệu suất thấp của mô hình của bạn.


6

Điều có khả năng nhất là đã có một số khái niệm trôi dạt. Vì mô hình của bạn được đào tạo về dữ liệu cho đến năm 2018 và được thử nghiệm vào năm 2019, mọi thứ đã thay đổi và một số thay đổi này mô hình của bạn có thể không thể thấy trước.

Một vài khả năng khác mặc dù:

Bạn nói rằng bạn đã thực hiện điều chỉnh siêu tham số, nhưng bỏ qua nó từ mã để đơn giản. Nhưng nếu bạn đang sử dụng bộ xác thực để chọn siêu đường kính, thì điểm số bạn nhận được sẽ bị sai lệch một cách lạc quan. (Nhưng bạn nói rằng mô hình chưa thấy bộ xác thực, vì vậy có thể đây không phải là cách bạn đang thực hiện.)

Cuối cùng, có thể bạn đã làm mọi thứ đúng, và thực sự không có khái niệm nào đang diễn ra, nhưng các hiệu ứng ngẫu nhiên đó chỉ chiếm một vài điểm chính xác.


2

Có hai lý do chính:

  1. Các mô hình được đào tạo có gần hiệu suất ngẫu nhiên. Ví dụ, 50% là hiệu suất ngẫu nhiên trong một nhiệm vụ phân loại nhị phân giả sử thành viên lớp bằng nhau. Nói cách khác, mô hình không học các mẫu dự đoán có ý nghĩa từ dữ liệu năm 2004 đến 2018.

  2. Có thể có các mẫu mới trong dữ liệu năm 2019. Các mẫu (hầu như không học) từ dữ liệu 2004 đến 2018 không chuyển sang dữ liệu 2019.


Ồ, vâng, bằng cách nào đó tôi đã bỏ lỡ rằng đây là phân loại nhị phân, rằng điểm số được báo cáo là chính xác, và chỉ 54% và 51%. +1
Ben Reiniger

0

Như câu thần chú đầu tư cũ, "hiệu suất trong quá khứ không phải là dấu hiệu của hiệu suất trong tương lai".

Ứng cử viên chính của tôi là quá mức. Mặc dù cơ hội cho một mẫu cụ thể có triệu chứng theo một hướng nhất định mặc dù nó không phải là nguyên nhân (hoặc dự đoán vượt ra ngoài mẫu), nhưng cũng có một số mẫu thiên văn được phát hiện có thể biểu hiện hành vi đó .

Giả sử chúng là những mô hình thực tế mà bạn đã học:
Trong khi bạn đang đào tạo một thuật toán học ba đáy và đầu và vai, hàng trăm ngân hàng cũng vậy, và làm việc đó nhanh hơn bạn và sử dụng thông tin đó.
Thông tin đó được phản ánh trong các biến động giá khác nhau, vì họ biết nhiều hơn năm 2018 và hành động khác nhau, mô hình của bạn không biết phải tính đến những hành động đó vì chúng là mới.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.