This commit is contained in:
2025-11-18 02:55:01 +03:00
parent 658e5f55f1
commit 3f13f2363c
20 changed files with 152363 additions and 15 deletions
+191
View File
@@ -0,0 +1,191 @@
import numpy as np
class Preprocessor:
def __init__(self):
pass
def fit(self, X, Y=None):
pass
def transform(self, X):
pass
def fit_transform(self, X, Y=None):
pass
class MyOneHotEncoder(Preprocessor):
def __init__(self, dtype=np.float64):
super(Preprocessor).__init__()
self.dtype = dtype
self.types = {}
def fit(self, X, Y=None):
"""
param X: training objects, pandas-dataframe, shape [n_objects, n_features]
param Y: unused
"""
for col in X.columns:
self.types[col] = sorted(X[col].unique())
def transform(self, X):
"""
param X: objects to transform, pandas-dataframe, shape [n_objects, n_features]
returns: transformed objects, numpy-array, shape [n_objects, |f1| + |f2| + ...]
"""
n_objects = X.shape[0]
n_features = sum(len(categories) for categories in self.types.vals())
res = np.zeros((n_objects, n_features))
shift_indexes = 0
for column, categories in self.types.items():
for i, category in enumerate(categories):
indices = np.where(X[column] == category)
res[indices, shift_indexes + i] = 1
shift_indexes += len(categories)
return res
def fit_transform(self, X, Y=None):
self.fit(X)
return self.transform(X)
def get_params(self, deep=True):
return {"dtype": self.dtype}
class SimpleCounterEncoder:
def __init__(self, dtype=np.float64):
self.dtype = dtype
self.count = {}
def fit(self, X, Y):
"""
param X: training objects, pandas-dataframe, shape [n_objects, n_features]
param Y: target for training objects, pandas-series, shape [n_objects,]
"""
for col in X.columns:
uniq_vals = X[col].unique()
self.count[col] = {}
for val in uniq_vals:
indexes = X[col] == val
self.count[col][val] = [Y[indexes].mean(), np.mean(indexes)]
def transform(self, X, a=1e-5, b=1e-5):
"""
param X: objects to transform, pandas-dataframe, shape [n_objects, n_features]
param a: constant for counters, float
param b: constant for counters, float
returns: transformed objects, numpy-array, shape [n_objects, 3 * n_features]
"""
n_obj, n_feach = X.shape
res = np.zeros((n_obj, 3 * n_feach))
for i, col in enumerate(X.columns):
for j in range(n_obj):
val = X.iloc[j, i]
mean_expected, frac = self.count[col][val]
res[j, 3 * i] = mean_expected
res[j, 3 * i + 1] = frac
res[j, 3 * i + 2] = (mean_expected + a) / (frac + b)
return res
def fit_transform(self, X, Y, a=1e-5, b=1e-5):
self.fit(X, Y)
return self.transform(X, a, b)
def get_params(self, deep=True):
return {"dtype": self.dtype}
def group_k_fold(size, n_splits=3, seed=1):
idx = np.arange(size)
np.random.seed(seed)
idx = np.random.permutation(idx)
n = size // n_splits
for i in range(n_splits - 1):
yield idx[i * n:(i + 1) * n], np.hstack((idx[: i * n], idx[(i + 1) * n:]))
yield idx[(n_splits - 1) * n:], idx[:(n_splits - 1) * n]
class FoldCounters:
def __init__(self, n_folds=3, dtype=np.float64):
self.dtype = dtype
self.n_folds = n_folds
self.fold_count = []
def fit(self, X, Y, seed=1):
"""
param X: training objects, pandas-dataframe, shape [n_objects, n_features]
param Y: target for training objects, pandas-series, shape [n_objects,]
param seed: random seed, int
"""
for fold_idx, rest_idx in group_k_fold(X.shape[0], self.n_folds, seed):
fold_counter = {}
X_fold, Y_fold = X.iloc[rest_idx], Y.iloc[rest_idx]
for column in X.columns:
unique_val = X_fold[column].unique()
fold_counter[column] = {}
for val in unique_val:
fold_counter[column][val] = [
Y_fold[X_fold[column] == val].mean(),
np.mean(X_fold[column] == val),
]
self.fold_count.append((fold_idx, fold_counter))
def transform(self, X, a=1e-5, b=1e-5):
"""
param X: objects to transform, pandas-dataframe, shape [n_objects, n_features]
param a: constant for counters, float
param b: constant for counters, float
returns: transformed objects, numpy-array, shape [n_objects, 3 * n_features]
"""
n_obj, n_feach = X.shape
res = np.zeros((n_obj, 3 * n_feach))
for fold_idx, fold_count in self.fold_count:
for i, column in enumerate(X.columns):
for j in fold_idx:
val = X.iloc[j, i]
mean_expected, frac = fold_count[column][val]
res[j, 3 * i] = mean_expected
res[j, 3 * i + 1] = frac
res[j, 3 * i + 2] = (mean_expected + a) / (frac + b)
return res
def fit_transform(self, X, Y, a=1e-5, b=1e-5):
self.fit(X, Y)
return self.transform(X, a, b)
def weights(x, y):
"""
param x: training set of one feature, numpy-array, shape [n_objects,]
param y: target for training objects, numpy-array, shape [n_objects,]
returns: optimal weights, numpy-array, shape [|x unique vals|,]
"""
uniq_vals = np.unique(x)
enc_x = np.eye(uniq_vals.shape[0])[x]
weight = np.zeros(enc_x.shape[1])
lr = 1e-2
for _ in range(1000):
p = np.dot(enc_x, weight)
grad = np.dot(enc_x.T, (p - y))
weight -= grad * lr
return weight