.
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user