|
|
|
|
|
"""kaggle_preprocessing_starter.ipynb |
|
|
|
|
|
Automatically generated by Colab. |
|
|
|
|
|
Original file is located at |
|
|
https://colab.research.google.com/drive/1Jzz9VWmE7n-HcdrXTuutXKHvAA1ry-5a |
|
|
|
|
|
# Kaggle Starter Notebook |
|
|
Базовые предобработки данных + быстрый старт моделей. |
|
|
|
|
|
# 🔥 Kaggle Starter Template: Предобработка + Генерация признаков + Модели |
|
|
|
|
|
Полный набор методов предобработки, генерации признаков, feature selection и моделей для соревнований Kaggle. |
|
|
Каждый метод снабжён пояснением. |
|
|
|
|
|
--- |
|
|
|
|
|
## 1. 🟦 Категориальные признаки |
|
|
|
|
|
### 1.1 OneHotEncoding (OHE) |
|
|
**Что делает:** Преобразует категорию в бинарные колонки. |
|
|
**Когда использовать:** Для линейных моделей, где порядок категорий не важен. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import OneHotEncoder |
|
|
import pandas as pd |
|
|
|
|
|
ohe = OneHotEncoder(sparse_output=False, handle_unknown="ignore") |
|
|
ohe_df = pd.DataFrame(ohe.fit_transform(df[['cat']]), |
|
|
columns=ohe.get_feature_names_out(['cat'])) |
|
|
```` |
|
|
|
|
|
### 1.2 LabelEncoding |
|
|
|
|
|
**Что делает:** Каждой категории присваивается число. |
|
|
**Когда использовать:** Для деревьев (RandomForest, XGBoost), избегать для линейных моделей. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import LabelEncoder |
|
|
le = LabelEncoder() |
|
|
df['cat_le'] = le.fit_transform(df['cat']) |
|
|
``` |
|
|
|
|
|
### 1.3 Target Encoding |
|
|
|
|
|
**Что делает:** Каждой категории присваивается среднее значение таргета. |
|
|
**Когда использовать:** Для категорий с сильной зависимостью от цели. |
|
|
**Внимание:** Возможна утечка информации, используйте KFold. |
|
|
|
|
|
```python |
|
|
!pip install category_encoders |
|
|
from category_encoders import TargetEncoder |
|
|
|
|
|
te = TargetEncoder() |
|
|
df['cat_te'] = te.fit_transform(df['cat'], df['target']) |
|
|
``` |
|
|
|
|
|
### 1.4 CatBoostEncoder |
|
|
|
|
|
**Что делает:** Улучшенный target encoding с регуляризацией и шумом. |
|
|
**Когда использовать:** Для уменьшения переобучения на малых выборках. |
|
|
|
|
|
```python |
|
|
from category_encoders import CatBoostEncoder |
|
|
|
|
|
cbe = CatBoostEncoder() |
|
|
df['cat_cbe'] = cbe.fit_transform(df['cat'], df['target']) |
|
|
``` |
|
|
|
|
|
### 1.5 Binary Encoding |
|
|
|
|
|
**Что делает:** Преобразует категорию в бинарный код. |
|
|
**Когда использовать:** Когда категорий слишком много для OHE. |
|
|
|
|
|
```python |
|
|
from category_encoders import BinaryEncoder |
|
|
|
|
|
be = BinaryEncoder() |
|
|
be_df = be.fit_transform(df['cat']) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 2. 🟩 Числовые признаки |
|
|
|
|
|
### 2.1 StandardScaler |
|
|
|
|
|
**Что делает:** Приводит к нулевому среднему и единичной дисперсии. |
|
|
**Когда использовать:** Для большинства моделей. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import StandardScaler |
|
|
df['scaled'] = StandardScaler().fit_transform(df[['num']]) |
|
|
``` |
|
|
|
|
|
### 2.2 RobustScaler |
|
|
|
|
|
**Что делает:** Масштабирование через медиану и IQR. |
|
|
**Когда использовать:** Если есть выбросы. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import RobustScaler |
|
|
df['r_scaled'] = RobustScaler().fit_transform(df[['num']]) |
|
|
``` |
|
|
|
|
|
### 2.3 MinMaxScaler |
|
|
|
|
|
**Что делает:** Масштабирует в диапазон [0,1]. |
|
|
**Когда использовать:** Для нейронных сетей. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import MinMaxScaler |
|
|
df['minmax'] = MinMaxScaler().fit_transform(df[['num']]) |
|
|
``` |
|
|
|
|
|
### 2.4 PowerTransformer |
|
|
|
|
|
**Что делает:** Нормализует распределение признака (Box-Cox / Yeo-Johnson). |
|
|
**Когда использовать:** Для сильно скошенных данных. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import PowerTransformer |
|
|
df['pt'] = PowerTransformer(method='yeo-johnson').fit_transform(df[['num']]) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 3. 🟧 Текстовые признаки |
|
|
|
|
|
### 3.1 TF-IDF |
|
|
|
|
|
**Что делает:** Преобразует текст в числовые векторы с учётом важности слов. |
|
|
**Когда использовать:** Для NLP-задач, классификации текста. |
|
|
|
|
|
```python |
|
|
from sklearn.feature_extraction.text import TfidfVectorizer |
|
|
|
|
|
tfidf = TfidfVectorizer(max_features=5000, ngram_range=(1,2)) |
|
|
tfidf_df = pd.DataFrame(tfidf.fit_transform(df['text']).toarray(), |
|
|
columns=tfidf.get_feature_names_out()) |
|
|
``` |
|
|
|
|
|
### 3.2 CountVectorizer |
|
|
|
|
|
**Что делает:** Считает количество слов. |
|
|
**Когда использовать:** Простая модель Bag-of-Words. |
|
|
|
|
|
```python |
|
|
from sklearn.feature_extraction.text import CountVectorizer |
|
|
|
|
|
cv = CountVectorizer(max_features=3000) |
|
|
cv_df = pd.DataFrame(cv.fit_transform(df['text']).toarray(), |
|
|
columns=cv.get_feature_names_out()) |
|
|
``` |
|
|
|
|
|
### 3.3 Word2Vec (Gensim) |
|
|
|
|
|
**Что делает:** Преобразует слова в векторы с помощью нейросети и усредняет по тексту. |
|
|
**Когда использовать:** Для семантических признаков текста. |
|
|
|
|
|
```python |
|
|
from gensim.models import Word2Vec |
|
|
import numpy as np |
|
|
|
|
|
w2v = Word2Vec(sentences=df['text'].str.split(), vector_size=100, window=5, min_count=1) |
|
|
df['w2v_mean'] = df['text'].str.split().apply( |
|
|
lambda x: w2v.wv[x].mean(axis=0) if len(x)>0 else np.zeros(100)) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 4. 🟪 Дата/время |
|
|
|
|
|
### 4.1 Извлечение компонентов даты |
|
|
|
|
|
**Что делает:** Получает год, месяц, день, день недели. |
|
|
**Когда использовать:** Для временных рядов или сезонных зависимостей. |
|
|
|
|
|
```python |
|
|
df['date'] = pd.to_datetime(df['date']) |
|
|
df['year'] = df['date'].dt.year |
|
|
df['month'] = df['date'].dt.month |
|
|
df['day'] = df['date'].dt.day |
|
|
df['dow'] = df['date'].dt.dayofweek |
|
|
df['is_weekend'] = df['dow'] >= 5 |
|
|
``` |
|
|
|
|
|
### 4.2 Циклические признаки для месяца/дня |
|
|
|
|
|
**Что делает:** Преобразует циклические признаки в син/кос для сохранения цикличности. |
|
|
|
|
|
```python |
|
|
import numpy as np |
|
|
df['month_sin'] = np.sin(2 * np.pi * df['month']/12) |
|
|
df['month_cos'] = np.cos(2 * np.pi * df['month']/12) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 5. 🟫 Статистические признаки и таймсериес |
|
|
|
|
|
### 5.1 Групповые агрегаты |
|
|
|
|
|
**Что делает:** Считает среднее, std, min, max по группам. |
|
|
**Когда использовать:** Для категориальных признаков, где важна статистика. |
|
|
|
|
|
```python |
|
|
group = df.groupby('cat')['num'].agg(['mean','std','min','max']) |
|
|
df = df.merge(group, on='cat', suffixes=('', '_grp')) |
|
|
``` |
|
|
|
|
|
### 5.2 Lag / Shift |
|
|
|
|
|
**Что делает:** Берёт предыдущие значения временного ряда. |
|
|
**Когда использовать:** Для прогнозирования временных рядов. |
|
|
|
|
|
```python |
|
|
df['lag1'] = df['value'].shift(1) |
|
|
df['lag2'] = df['value'].shift(2) |
|
|
``` |
|
|
|
|
|
### 5.3 Rolling / Скользящее окно |
|
|
|
|
|
**Что делает:** Считает агрегаты (mean, sum, std) по окну. |
|
|
**Когда использовать:** Для извлечения трендов в таймсериях. |
|
|
|
|
|
```python |
|
|
df['rolling_mean_3'] = df['value'].rolling(3).mean() |
|
|
df['rolling_std_3'] = df['value'].rolling(3).std() |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 6. 🟨 Feature Selection |
|
|
|
|
|
### 6.1 Mutual Information |
|
|
|
|
|
**Что делает:** Оценивает зависимость признака и целевой переменной. |
|
|
**Когда использовать:** Для отбора информативных признаков. |
|
|
|
|
|
```python |
|
|
from sklearn.feature_selection import mutual_info_classif |
|
|
|
|
|
mi = mutual_info_classif(X, y) |
|
|
``` |
|
|
|
|
|
### 6.2 SelectKBest |
|
|
|
|
|
**Что делает:** Выбирает K лучших признаков по метрике (ANOVA, MI и др.) |
|
|
|
|
|
```python |
|
|
from sklearn.feature_selection import SelectKBest, f_classif |
|
|
|
|
|
selector = SelectKBest(score_func=f_classif, k=20) |
|
|
X_new = selector.fit_transform(X, y) |
|
|
``` |
|
|
|
|
|
### 6.3 RFE (Recursive Feature Elimination) |
|
|
|
|
|
**Что делает:** Рекурсивно удаляет наименее важные признаки, оставляя n лучших. |
|
|
**Когда использовать:** Для моделей с interpretability. |
|
|
|
|
|
```python |
|
|
from sklearn.feature_selection import RFE |
|
|
from sklearn.linear_model import LogisticRegression |
|
|
|
|
|
rfe = RFE(LogisticRegression(), n_features_to_select=10) |
|
|
rfe.fit(X, y) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 7. 🟫 Feature Generation |
|
|
|
|
|
### 7.1 Polynomial Features |
|
|
|
|
|
**Что делает:** Создаёт полиномиальные признаки (x^2, x*y). |
|
|
**Когда использовать:** Для линейных моделей, чтобы учесть нелинейности. |
|
|
|
|
|
```python |
|
|
from sklearn.preprocessing import PolynomialFeatures |
|
|
|
|
|
poly = PolynomialFeatures(degree=3) |
|
|
poly_df = pd.DataFrame(poly.fit_transform(df[['num1','num2']])) |
|
|
``` |
|
|
|
|
|
### 7.2 Interaction Features |
|
|
|
|
|
**Что делает:** Создаёт признаки через перемножение/деление. |
|
|
**Когда использовать:** Для деревьев и линейных моделей. |
|
|
|
|
|
```python |
|
|
df['num1_x_num2'] = df['num1'] * df['num2'] |
|
|
df['num1_div_num2'] = df['num1'] / (df['num2'] + 1e-5) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 8. 🔥 Модели: классификация |
|
|
|
|
|
```python |
|
|
from catboost import CatBoostClassifier |
|
|
from xgboost import XGBClassifier |
|
|
from lightgbm import LGBMClassifier |
|
|
from sklearn.linear_model import LogisticRegression |
|
|
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier, ExtraTreesClassifier |
|
|
from sklearn.svm import SVC |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 9. 🔥 Модели: регрессия |
|
|
|
|
|
```python |
|
|
from xgboost import XGBRegressor |
|
|
from lightgbm import LGBMRegressor |
|
|
from catboost import CatBoostRegressor |
|
|
from sklearn.ensemble import RandomForestRegressor |
|
|
from sklearn.linear_model import LinearRegression, Ridge, Lasso |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 10. 🧱 Полный Pipeline |
|
|
|
|
|
**Что делает:** Объединяет числовые, категориальные признаки, pre-processing и модель в один объект. |
|
|
|
|
|
```python |
|
|
from sklearn.compose import ColumnTransformer |
|
|
from sklearn.pipeline import Pipeline |
|
|
from sklearn.preprocessing import StandardScaler, OneHotEncoder |
|
|
from lightgbm import LGBMClassifier |
|
|
|
|
|
numeric = ['age','salary'] |
|
|
categorical = ['city'] |
|
|
|
|
|
preprocess = ColumnTransformer([ |
|
|
('num', StandardScaler(), numeric), |
|
|
('cat', OneHotEncoder(handle_unknown='ignore'), categorical), |
|
|
]) |
|
|
|
|
|
model = Pipeline([ |
|
|
('prep', preprocess), |
|
|
('clf', LGBMClassifier()) |
|
|
]) |
|
|
|
|
|
model.fit(X_train, y_train) |
|
|
pred = model.predict(X_test) |
|
|
``` |
|
|
|
|
|
``` |
|
|
|
|
|
# 🧠 Продвинутое обучение моделей: классификация и регрессия |
|
|
|
|
|
## 1. Базовые модели |
|
|
|
|
|
### 1.1 Линейные модели |
|
|
|
|
|
**Логистическая регрессия (классификация)** |
|
|
```python |
|
|
from sklearn.linear_model import LogisticRegression |
|
|
|
|
|
clf = LogisticRegression(max_iter=1000) |
|
|
clf.fit(X_train, y_train) |
|
|
preds = clf.predict(X_test) |
|
|
```` |
|
|
|
|
|
**Линейная регрессия (регрессия)** |
|
|
|
|
|
```python |
|
|
from sklearn.linear_model import LinearRegression |
|
|
|
|
|
reg = LinearRegression() |
|
|
reg.fit(X_train, y_train) |
|
|
preds = reg.predict(X_test) |
|
|
``` |
|
|
|
|
|
**Ridge / Lasso (регуляризация)** |
|
|
|
|
|
```python |
|
|
from sklearn.linear_model import Ridge, Lasso |
|
|
|
|
|
ridge = Ridge(alpha=1.0) |
|
|
ridge.fit(X_train, y_train) |
|
|
|
|
|
lasso = Lasso(alpha=0.01) |
|
|
lasso.fit(X_train, y_train) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
### 1.2 Деревья и ансамбли |
|
|
|
|
|
**RandomForest** |
|
|
|
|
|
```python |
|
|
from sklearn.ensemble import RandomForestClassifier, RandomForestRegressor |
|
|
|
|
|
rf_clf = RandomForestClassifier(n_estimators=200, max_depth=8, random_state=42) |
|
|
rf_clf.fit(X_train, y_train) |
|
|
|
|
|
rf_reg = RandomForestRegressor(n_estimators=200, max_depth=8, random_state=42) |
|
|
rf_reg.fit(X_train, y_train) |
|
|
``` |
|
|
|
|
|
**Gradient Boosting** |
|
|
|
|
|
```python |
|
|
from sklearn.ensemble import GradientBoostingClassifier, GradientBoostingRegressor |
|
|
|
|
|
gb_clf = GradientBoostingClassifier(n_estimators=300, learning_rate=0.05) |
|
|
gb_clf.fit(X_train, y_train) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
### 1.3 Популярные бустинги |
|
|
|
|
|
**XGBoost** |
|
|
|
|
|
```python |
|
|
from xgboost import XGBClassifier, XGBRegressor |
|
|
|
|
|
xgb_clf = XGBClassifier(n_estimators=300, learning_rate=0.05, max_depth=5, eval_metric='logloss') |
|
|
xgb_clf.fit(X_train, y_train) |
|
|
``` |
|
|
|
|
|
**LightGBM** |
|
|
|
|
|
```python |
|
|
from lightgbm import LGBMClassifier, LGBMRegressor |
|
|
|
|
|
lgb_clf = LGBMClassifier(n_estimators=500, learning_rate=0.05, num_leaves=31) |
|
|
lgb_clf.fit(X_train, y_train) |
|
|
``` |
|
|
|
|
|
**CatBoost** |
|
|
|
|
|
```python |
|
|
from catboost import CatBoostClassifier, CatBoostRegressor |
|
|
|
|
|
cat_clf = CatBoostClassifier(iterations=500, learning_rate=0.05, depth=6, verbose=0) |
|
|
cat_clf.fit(X_train, y_train) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 2. K-Fold Cross-Validation |
|
|
|
|
|
**Что делает:** Делит данные на K частей, обучает K моделей, усредняет метрики и предсказания. |
|
|
|
|
|
```python |
|
|
from sklearn.model_selection import KFold |
|
|
from sklearn.metrics import accuracy_score |
|
|
import numpy as np |
|
|
|
|
|
kf = KFold(n_splits=5, shuffle=True, random_state=42) |
|
|
oof_preds = np.zeros(len(X)) |
|
|
for train_idx, val_idx in kf.split(X): |
|
|
X_tr, X_val = X[train_idx], X[val_idx] |
|
|
y_tr, y_val = y[train_idx], y[val_idx] |
|
|
|
|
|
model = LGBMClassifier(n_estimators=500) |
|
|
model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], early_stopping_rounds=50, verbose=0) |
|
|
|
|
|
oof_preds[val_idx] = model.predict(X_val) |
|
|
|
|
|
# Средняя точность |
|
|
from sklearn.metrics import accuracy_score |
|
|
accuracy_score(y, oof_preds) |
|
|
``` |
|
|
|
|
|
**Пояснение:** |
|
|
|
|
|
* `early_stopping_rounds` помогает остановить обучение, если модель не улучшается |
|
|
* `shuffle=True` перемешивает данные для устойчивости |
|
|
|
|
|
--- |
|
|
|
|
|
## 3. Метрики |
|
|
|
|
|
### 3.1 Классификация |
|
|
|
|
|
```python |
|
|
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score |
|
|
|
|
|
accuracy = accuracy_score(y_test, preds) |
|
|
f1 = f1_score(y_test, preds) |
|
|
roc_auc = roc_auc_score(y_test, probs[:,1]) # для бинарного случая |
|
|
``` |
|
|
|
|
|
### 3.2 Регрессия |
|
|
|
|
|
```python |
|
|
from sklearn.metrics import mean_squared_error, r2_score |
|
|
|
|
|
mse = mean_squared_error(y_test, preds) |
|
|
rmse = np.sqrt(mse) |
|
|
r2 = r2_score(y_test, preds) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 4. Early Stopping (для бустингов) |
|
|
|
|
|
```python |
|
|
lgb_clf = LGBMClassifier(n_estimators=10000, learning_rate=0.01) |
|
|
lgb_clf.fit( |
|
|
X_train, y_train, |
|
|
eval_set=[(X_val, y_val)], |
|
|
eval_metric='logloss', |
|
|
early_stopping_rounds=100, |
|
|
verbose=100 |
|
|
) |
|
|
``` |
|
|
|
|
|
--- |
|
|
|
|
|
## 5. Stacking / Blending |
|
|
|
|
|
**Что делает:** Комбинирует предсказания нескольких моделей через meta-модель. |
|
|
|
|
|
```python |
|
|
from sklearn.ensemble import StackingClassifier |
|
|
from sklearn.linear_model import LogisticRegression |
|
|
|
|
|
estimators = [ |
|
|
('rf', RandomForestClassifier(n_estimators=100)), |
|
|
('xgb', XGBClassifier(n_estimators=100)), |
|
|
('lgb', LGBMClassifier(n_estimators=100)) |
|
|
] |
|
|
|
|
|
stack = StackingClassifier( |
|
|
estimators=estimators, |
|
|
final_estimator=LogisticRegression() |
|
|
) |
|
|
stack.fit(X_train, y_train) |
|
|
preds = stack.predict(X_test) |
|
|
``` |
|
|
|
|
|
**Пояснение:** |
|
|
|
|
|
* Каждый базовый классификатор делает предсказания |
|
|
* Meta-модель (например, LogisticRegression) обучается на этих предсказаниях |
|
|
|
|
|
--- |
|
|
|
|
|
## 6. Feature Importance |
|
|
|
|
|
**Для деревьев и бустингов:** |
|
|
|
|
|
```python |
|
|
import matplotlib.pyplot as plt |
|
|
|
|
|
model = LGBMClassifier(n_estimators=500) |
|
|
model.fit(X_train, y_train) |
|
|
|
|
|
feat_importances = pd.Series(model.feature_importances_, index=X.columns) |
|
|
feat_importances.nlargest(20).plot(kind='barh') |
|
|
plt.show() |
|
|
``` |
|
|
|
|
|
**Пояснение:** |
|
|
|
|
|
* Позволяет увидеть, какие признаки влияют на модель |
|
|
* Можно отбирать топовые фичи для уменьшения размерности |
|
|
|
|
|
--- |
|
|
|
|
|
## 7. Randomized Search / Grid Search (Подбор гиперпараметров) |
|
|
|
|
|
```python |
|
|
from sklearn.model_selection import RandomizedSearchCV |
|
|
|
|
|
param_grid = { |
|
|
'n_estimators': [100, 300, 500], |
|
|
'max_depth': [3, 5, 7], |
|
|
'learning_rate': [0.01, 0.05, 0.1] |
|
|
} |
|
|
|
|
|
rs = RandomizedSearchCV(LGBMClassifier(), param_grid, cv=3, scoring='accuracy', n_iter=5) |
|
|
rs.fit(X_train, y_train) |
|
|
rs.best_params_ |
|
|
``` |
|
|
|
|
|
**Пояснение:** |
|
|
|
|
|
* Автоматически ищет лучшие гиперпараметры |
|
|
* `n_iter` контролирует количество проб |
|
|
|
|
|
--- |
|
|
|
|
|
## 8. Пример пайплайна с K-Fold и несколькими моделями |
|
|
|
|
|
```python |
|
|
from sklearn.model_selection import KFold |
|
|
import numpy as np |
|
|
|
|
|
kf = KFold(n_splits=5, shuffle=True, random_state=42) |
|
|
oof_preds = np.zeros(len(X)) |
|
|
models = [] |
|
|
|
|
|
for train_idx, val_idx in kf.split(X): |
|
|
X_tr, X_val = X[train_idx], X[val_idx] |
|
|
y_tr, y_val = y[train_idx], y[val_idx] |
|
|
|
|
|
model = CatBoostClassifier(iterations=1000, learning_rate=0.05, depth=6, verbose=0) |
|
|
model.fit(X_tr, y_tr, eval_set=[(X_val, y_val)], early_stopping_rounds=50) |
|
|
|
|
|
oof_preds[val_idx] = model.predict(X_val) |
|
|
models.append(model) |
|
|
|
|
|
accuracy_score(y, oof_preds) |
|
|
""" |
|
|
|
|
|
import numpy as np |
|
|
|
|
|
|
|
|
preds_list = [pred1, pred2, pred3] |
|
|
weights = np.array([2.0, 1.0, 3.0]) |
|
|
|
|
|
|
|
|
weights = weights / weights.sum() |
|
|
|
|
|
|
|
|
final_pred = np.zeros_like(preds_list[0], dtype=float) |
|
|
|
|
|
for pred, w in zip(preds_list, weights): |
|
|
final_pred += pred * w |