Wednesday, August 11, 2021

WOE

 #http://lazynight.me/4048.html

import math

import numpy as np
from scipy import stats
from sklearn.utils.multiclass import type_of_target


class WOE(object):
    def __init__(self):
        self._WOE_MIN = -20
        self._WOE_MAX = 20

    def processing(self, X, y, event=1):
        self.check_target_binary(y)
        X1 = self.feature_discretion(X)

        res_woe = []
        res_iv = []
        for i in range(0, X1.shape[-1]):
            x = X1[:, i]
            woe_dict, iv1 = self.woe_single_x(x, y, event)
            res_woe.append(woe_dict)
            res_iv.append(iv1)
        return np.array(res_woe), np.array(res_iv)

    def woe_single_x(self, x, y, event=1):
        self.check_target_binary(y)

        event_total, non_event_total = self.count_binary(y, event=event)
        x_labels = np.unique(x)
        woe_dict = {}
        iv = 0
        for x1 in x_labels:
            y1 = y[np.where(x == x1)[0]]
            event_count, non_event_count = self.count_binary(y1, event=event)
            rate_event = 1.0 * event_count / event_total
            rate_non_event = 1.0 * non_event_count / non_event_total
            if rate_event == 0:
                woe1 = self._WOE_MIN
            elif rate_non_event == 0:
                woe1 = self._WOE_MAX
            else:
                woe1 = math.log(rate_event / rate_non_event)
            woe_dict[x1] = woe1
            iv += (rate_event - rate_non_event) * woe1
        return woe_dict, iv

    def woe_replace(self, X, woe_arr):
        if X.shape[-1] != woe_arr.shape[-1]:
            raise ValueError('WOE dict array length must be equal with features length')

        res = np.copy(X).astype(float)
        idx = 0
        for woe_dict in woe_arr:
            for k in woe_dict.keys():
                woe = woe_dict[k]
                res[:, idx][np.where(res[:, idx] == k)[0]] = woe * 1.0
            idx += 1

        return res

    def combined_iv(self, X, y, masks, event=1):
        if masks.shape[-1] != X.shape[-1]:
            raise ValueError('Masks array length must be equal with features length')

        x = X[:, np.where(masks == 1)[0]]
        tmp = []
        for i in range(x.shape[0]):
            tmp.append(self.combine(x[i, :]))

        dumy = np.array(tmp)
        # dumy_labels = np.unique(dumy)
        woe, iv = self.woe_single_x(dumy, y, event)
        return woe, iv

    def combine(self, list):
        res = ''
        for item in list:
            res += str(item)
        return res

    def count_binary(self, a, event=1):
        event_count = (a == event).sum()
        non_event_count = a.shape[-1] - event_count
        return event_count, non_event_count

    def check_target_binary(self, y):
        y_type = type_of_target(y)
        if y_type not in ['binary']:
            raise ValueError('Label type must be binary')

    def feature_discretion(self, X):
        temp = []
        for i in range(0, X.shape[-1]):
            x = X[:, i]
            x_type = type_of_target(x)
            if x_type == 'continuous':
                x1 = self.discrete(x)
                temp.append(x1)
            else:
                temp.append(x)
        return np.array(temp).T

    def discrete(self, x):
        res = np.array([0] * x.shape[-1], dtype=int)
        for i in range(5):
            point1 = stats.scoreatpercentile(x, i * 20)
            point2 = stats.scoreatpercentile(x, (i + 1) * 20)
            x1 = x[np.where((x >= point1) & (x <= point2))]
            mask = np.in1d(x, x1)
            res[mask] = (i + 1)
        return res

    @property
    def WOE_MIN(self):
        return self._WOE_MIN

    @WOE_MIN.setter
    def WOE_MIN(self, woe_min):
        self._WOE_MIN = woe_min

    @property
    def WOE_MAX(self):
        return self._WOE_MAX

    @WOE_MAX.setter
    def WOE_MAX(self, woe_max):
        self._WOE_MAX = woe_max

Street suffix abbreviations

# Street suffix abbreviations 

# https://pe.usps.com/text/pub28/28apc_002.htm

addressStandardMap = {'ALLEE': 'ALLEY',

                      'ALLY' : 'ALLEY',

                      'ALY':   'ALLEY',

                      'ANEX':  'ANNEX',

                      'ANNX':  'ANNEX',

                      'ANX':   'ANNEX',

                      'ARC':   'ARCADE',

                      'AV':     'AVENUE',

                      'AVE': 'AVENUE',

                      'AVEN': 'AVENUE',

                      'AVENU': 'AVENUE',

                      'AVN': 'AVENUE',

                      'AVNUE': 'AVENUE',

                      'BYU': 'BAYOU',

                      'BAYOO': 'BAYOU',

                      'BND': 'BEND',

                      'BLF': 'BLUFF',

                      'BLUF': 'BLUFF',

                      'BLFS': 'BLUFFS',

                      'BTM': 'BOTTOM',

                      'BOT': 'BOTTOM',

                      'BOTTM': 'BOTTOM',

                      'BLVD': 'BOULEVARD',

                      'BOUL': 'BOULEVARD',

                      'BOULV': 'BOULEVARD',

                      'BR': 'BRANCH',

                      'BRNCH': 'BRANCH',

                      'BRDGE': 'BRIDGE',

                      'BRG': 'BRIDGE',

                      'BRK': 'BROOK',

                      'BRKS': 'BROOKS',

                      'BG': 'BURG',

                      'BGS': 'BURGS',

                      'BYP': 'BYPASS',

                      'BYPA': 'BYPASS',

                      'BYPAS': 'BYPASS',

                      'BYPS': 'BYPASS',

                      'CP': 'CAMP',

                      'CMP': 'CAMP',

                      'CANYN': 'CANYON',

                      'CNYN': 'CANYON',

                      'CPE': 'CAPE',

                      'CSWY': 'CAUSEWAY',

                      'CAUSWA': 'CAUSEWAY',

                      'CTR': 'CENTER',

                      'CEN': 'CENTER',

                      'CENT': 'CENTER',

                      'CENTR': 'CENTER',

                      'CENTRE': 'CENTER',

                      'CNTER': 'CENTER',

                      'CNTR': 'CENTER',

                      'CTRS': 'CENTERS',

                      'CIR': 'CIRCLE',

                      'CIRC': 'CIRCLE',

                      'CIRCL': 'CIRCLE',

                      'CRCL': 'CIRCLE',

                      'CIRS': 'CIRCLES',

                      'CLF': 'CLIFF',

                      'CLFS': 'CLIFFS',

                      'CLB': 'CLB',

                      'CMN': 'COMMMON',

                      'CMNS': 'COMMONS',

                      'COR': 'CORNER',

                      'CORS': 'CORNERS',

                      'CRSE': 'COURSE',

                      'CT': 'COURT',

                      'CTS': 'COURTS',

                      'CV': 'COVE',

                      'CVS': 'COVES',

                      'CRK': 'CREEK',

                      'XING': 'CROSSING',

                      'CRSSNG': 'CROSSING',

                      'XRD': 'CROSSROAD',

                      'XRDS': 'CROSSROADS',

                      'CURV': 'CURVE',

                      'DL': 'DALE',

                      'DM': 'DAM',

                      'DV': 'DIVIDE',

                      'DIV': 'DIVIDE',

                      'DVD': 'DIVIDE',

                      'DR': 'DRIVE',

                      'DRIV': 'DRIVE',

                      'DRV': 'DRIVE',

                      'DRS': 'DRIVES',

                      'EST': 'ESTATE',

                      'ESTS': 'ESTATES',

                      'EXPY': 'EXPRESSWAY',

                      'EXP': 'EXPRESSWAY',

                      'EXPR': 'EXPRESSWAY',

                      'EXPW': 'EXPRESSWAY',

                      'EXPRESS': 'EXPRESSWAY',

                      'EXT': 'EXTENSION',

                      'EXTN': 'EXTENSION',

                      'EXTNSN': 'EXTENSION',

                      'EXTS': 'EXTENSIONS',

                      'FLS': 'FALLS',

                      'FRY': 'FERRY',

                      'FRRY': 'FERRY',

                      'FLD': 'FIELD',

                      'FLDS': 'FIELDS',

                      'FLT': 'FLAT',

                      'FLTS': 'FLATS',

                      'FRD': 'FORD',

                      'FRDS': 'FORDS',

                      'FRST': 'FORESTS',

                      'FOEREST': 'FORESTS',

                      'FRG': 'FORGE',

                      'FORG': 'FORGE',

                      'FRGS': 'FORGES',

                      'FRK': 'FORK',

                      'FRKS': 'FORKS',

                      'FT': 'FORT',

                      'FRT': 'FORT',

                      'FWY': 'FREEWAY',

                      'FREEWY': 'FREEWAY',

                      'FRWY': 'FREEWAY',

                      'FRWAY': 'FREEWAY',

                      'GDN': 'GARDEN',

                      'GARDN': 'GARDEN',

                      'GRDN': 'GARDEN',

                      'GDNS': 'GARDENS',

                      'GRDNS': 'GARDENS',

                      'GATEWY': 'GATEWAY',

                      'GATWAY': 'GATEWAY',

                      'GTEWAY': 'GATEWAY',

                      'GTWY': 'GATEWAY',

                      'GLN': 'GLEN',

                      'GLNS': 'GLENS',

                      'GRN': 'GREEN',

                      'GRNS': 'GREENS',

                      'GRV': 'GROVE',

                      'GROV': 'GROVE',

                      'GRVS': 'GROVES',

                      'HBR': 'HARBOR',

                      'HARBR': 'HARBOR',

                      'HARB': 'HARBOR',

                      'HRBOR': 'HARBOR',

                      'HBRS': 'HARBORS',

                      'HVN': 'HAVEN',

                      'HTS': 'HEIGHTS',

                      'HT': 'HEIGHTS',

                      'HWY': 'HIGHWAY',

                      'HIGHWY': 'HIGHWAY',

                      'HIWAY': 'HIGHWAY',

                      'HWAY': 'HIGHWAY',

                      'HIWY': 'HIGHWAY',

                      'HL': 'HILL',

                      'HLS': 'HILLS',

                      'HOLW': 'HOLLOWS',

                      'HLLW': 'HOLLOWS',

                      'HOLLOW': 'HOLLOWS',

                      'HOLWS': 'HOLLOWS',

                      'INLT': 'INLET',

                      'IS': 'ISLAND',

                      'ISLND': 'ISLAND',

                      'ISS': 'ISLANDS',

                      'ISLNDS': 'ISLANDS',

                      'ISLE': 'ISLES',

                      'JCT': 'JUNCTION',

                      'JCTION': 'JUNCTION',

                      'JCTN': 'JUNCTION',

                      'JUNCTN': 'JUNCTION',

                      'JUNCTON': 'JUNCTION',

                      'JCTS': 'JUNCTIONS',

                      'JCTNS': 'JUNCTIONS',

                      'KY': 'KEY',

                      'KYS': 'KEYS',

                      'KNL': 'KNOLL',

                      'KNOL': 'KNOLL',

                      'KNLS': 'KNOLLS',

                      'LK': 'LAKE',

                      'LKS': 'LAKES',

                      'LNDG': 'LANDING',

                      'LNDNG': 'LANDING',

                      'LN': 'LANE',

                      'LGT': 'LIGHT',

                      'LGTS': 'LIGHTS',

                      'LF': 'LOAF',

                      'LCK': 'LOCK',

                      'LCKS': 'LOCKS',

                      'LDG': 'LODGE',

                      'LDGE': 'LODGE',

                      'LODG': 'LODGE',

                      'LOOP': 'LOOPS',

                      'MNR': 'MANOR',

                      'MNRS': 'MANORS',

                      'MDW': 'MEADOW',

                      'MDWS': 'MEADOWS',

                      'MEDOWS': 'MEADOWS',

                      'MIL': 'MILL',

                      'MLS': 'MILLS',

                      'MSN': 'MISSION',

                      'MSSN': 'MISSION',

                      'MISSN': 'MISSION',

                      'MTWY': 'MOTORWAY',

                      'MT': 'MOUNT',

                      'MNT': 'MOUNT',

                      'NCK': 'NECK',

                      'ORCH': 'ORCHARD',

                      'ORCHRD': 'ORCHARD',

                      'OVL': 'OVAL',

                      'OPAS': 'OVERPASS',

                      'PRK': 'PARKS',

                      'PARK': 'PARKS',

                      'PKWY': 'PARKWAYS',

                      'PARKWY': 'PARKWAYS',

                      'PKWAY': 'PARKWAYS',

                      'PKY': 'PARKWAYS',

                      'PKWYS': 'PARKWAYS',

                      'PSGE': 'PASSAGE',

                      'PATH': 'PATHS',

                      'PIKE': 'PIKES',

                      'PNE': 'PINE',

                      'PNES': 'PINES',

                      'PL': 'PLACE',

                      'PLN': 'PLAIN',

                      'PLNS': 'PLAINS',

                      'PLZ': 'PLAZA',

                      'PLZA': 'PLAZA',

                      'PT': 'POINT',

                      'PTS': 'POINTS',

                      'PRTS': 'PORTS',

                      'PR': 'PRAIRIE',

                      'RADL': 'RADIAL',

                      'RAD': 'RADIAL',

                      'RADIEL': 'RADIAL',

                      'RNCH': 'RANCH',

                      'RANCHES': 'RANCH',

                      'RNCHS': 'RANCH',

                      'RPD': 'RAPID',

                      'RPDS': 'RAPIDS',

                      'RST': 'REST',

                      'RDG': 'RIDGE',

                      'RDGE': 'RIDGE',

                      'RDGS': 'RIDGES',

                      'RIV': 'RIVER',

                      'RVR': 'RIVER',

                      'RIVR': 'RIVER',

                      'RD': 'ROAD',

                      'RDS': 'ROADS',

                      'RTE': 'ROUTE',

                      'SHL': 'SHOAL',

                      'SHLS': 'SHOALS',

                      'SHR': 'SHORE',

                      'SHOAR': 'SHORE',

                      'SHRS': 'SHORES',

                      'SHOARS': 'SHORES',

                      'SKWY': 'SKYWAY',

                      'SPG': 'SPRING',

                      'SPNG': 'SPRING',

                      'SPRNG': 'SPRING',

                      'SPGS': 'SPRINGS',

                      'SPNGS': 'SPRINGS',

                      'SPRNGS': 'SPRINGS',

                      'SPURS': 'SPUR',

                      'SQ': 'SQUARE',

                      'SQR': 'SQUARE',

                      'SQRE': 'SQUARE',

                      'SQU': 'SQUARE',

                      'SQS': 'SQUARES',

                      'STA': 'STATION',

                      'STATN': 'STATION',

                      'STN': 'STATION',

                      'STRA': 'STRAVENUE',

                      'STRAV': 'STRAVENUE',

                      'STRAVEN': 'STRAVENUE',

                      'STRAVN': 'STRAVENUE',

                      'STRVN': 'STRAVENUE',

                      'STRVNUE': 'STRAVENUE',

                      'STRM': 'STREAM',

                      'STREME': 'STREAM',

                      'ST': 'STREET',

                      'STRT': 'STREET',

                      'STR': 'STREET',

                      'STS': 'STREETS',

                      'SMT': 'SUMMIT',

                      'SUMIT': 'SUMMIT',

                      'SUMITT': 'SUMMIT',

                      'TER': 'TERRACE',

                      'TERR': 'TERRACE',

                      'TRWY': 'THROUGHWAY',

                      'TRCE': 'TRACE',

                      'TRACES': 'TRACE',

                      'TRAK': 'TRACKS',

                      'TRACK': 'TRACKS',

                      'TRKS': 'TRACKS',

                      'TRK': 'TRACKS',

                      'TRFY': 'TRAFFICWAY',

                      'TRL': 'TRAILS',

                      'TRAIL': 'TRAILS',

                      'TRLS': 'TRAILS',

                      'TRLR': 'TRAILER',

                      'TRLRS': 'TRAILER',

                      'TUNL': 'TUNNUEL',

                      'TUNEL': 'TUNNUEL',

                      'TUNLS': 'TUNNUEL',

                      'TUNNELS': 'TUNNUEL',

                      'TUNNL': 'TUNNUEL',

                      'TPKE': 'TURNPIKE',

                      'TRNPK': 'TURNPIKE',

                      'UPAS': 'UNDERPASS',

                      'UN': 'UNION',

                      'UNS': 'UNIONS',

                      'VLY': 'VALLEY',

                      'VALLY': 'VALLEY',

                      'VLLY': 'VALLEY',

                      'VLYS': 'LAVVELYS',

                      'VIA': 'VIADUCT',

                      'VDCT': 'VIADUCT',

                      'VW': 'VIEW',

                      'VWS': 'VIEWS',

                      'VLG': 'VILLAGE',

                      'VILL': 'VILLAGE',

                      'VILLAG': 'VILLAGE',

                      'VILLG': 'VILLAGE',

                      'VILLIAGE': 'VILLAGE',

                      'VLGS': 'VILLAGES',

                      'VL': 'VILLE',

                      'VIS': 'VISTA',

                      'VIST': 'VISTA',

                      'VST': 'VISTA',

                      'VSTA': 'VISTA',

                      'WALK': 'WALKS',

                      'WY': 'WAY',

                      'WL': 'WELL',

                      'WLS': 'WELLS'}

Monday, August 9, 2021

some bash alias I found very useful

 # User specific aliases and functions

alias showheader='head -1|tr "," "\n" | tr "|" "\n" |tr "^" "\n" |  nl -ba | less'

alias pnfc='awk -F"," "{print NF}"'

alias pnfp='awk -F"|" "{print NF}"'

alias mytop='top -u <username>'

alias cl='clear'

alias head5='head -5'

alias head2='head -2'

alias head1='head -1'

alias lsht='ls -lsh --sort=time'

alias lshs='ls -lsh --sort=size'

alias savehist='history | tail -2 | head -1 >> NOTES'

alias x='chmod +x'

alias ssactivate='source activate <env name>'

alias cls='clear'

alias lsl='ls -alh --color=auto'

alias du='du -h'

alias df='df -h'

alias jnotebook='jupyter notebook --port 8890 --no-browser'

alias screenkillall='screen -ls | grep pts | cut -d. -f1 | awk "{print $1}" | xargs kill'

alias screenkilldetached='screen -ls | grep Detached | cut -d. -f1 | awk "{print $1}" | xargs kill'

alias savedate='echo ~~~~~~~~~~~~~~~~~~~~$(date)~~~~~~~~~~~~~~~~~~~~ >> NOTES'

dec(){

    openssl des3 -in "$1" -d -pass pass:<password>

}

export -f dec

Tuesday, March 16, 2021

rename files within a directory one by one, using for loop and mv


for f in dir/*; do
    mv -- "$f" "$fSuffix" 
done 
So all the files in the dir/ will be renamed:
file1.txt --> file1.txtSuffix
file2.png --> file2.pngSuffix

Copy s3 files selected by dates

 $ aws s3 ls s3://<bucket-name> --recursive | awk '/^2018-11-06/{system("aws s3 cp s3://<bucket-name>/$4 .") }'

Tuesday, March 3, 2020

Building a XGBoost model

1. pre-process :

           1.1 Boruta to clean data column-wise
           1.2 TomekLinks to clean data row-wise

2. training (use a random sample to do this step if the data size is too big):

          2.1 create a basic with fixed learning rate and n_estimators:
                                       XGBRFClassifier(objective='binary:logistic',
                                                                     n_estimator=X,
                                                                     learning_rate=0.1,
                                                                     n_jobs=-1)
         
          2.2 grid search for optimal 'max_depth' and 'min_child_weight'.
                          -- use scoring='roc_auc'
                          -- use cv = RepeatedStratifiedKFold(n_splits=3, n_repeats=3)

          2.3 get 'current_best' by using gridsearch.best_estimator, then fit current_best again.

         2.4 then grid search for 'gamma' with current_best, when it's done, get 'current_best' by using gridsearch.best_estimator, then fit current_best again.

         2.5 then grid search for 'subsample' and 'colsample_bytree', when it's done, get 'current_best' by using gridsearch.best_estimator, then fit current_best again.

         2.6 then grid search for 'learning_rate' , when it's done, get 'current_best' by using gridsearch.best_estimator, then fit current_best again.


3. final training: use all data to fit the mdl with all the optimized params.

4. Evaluatiion.
                 
               

Friday, February 28, 2020

Assign bin labels to new values during model inference

In model development:

import pandas as pd
import numpy as np
np.random.seed(42)

bins = [0, 10, 15, 20, 25, 30, np.inf]
labels = bins[1:]
ages = list(range(5, 90, 5))
df = pd.DataFrame({"user_age": ages})
df["user_age_bin"] = pd.cut(df["user_age"], bins=bins, labels=False)

# sort by age 
print(df.sort_values('user_age'))


In production, I will need to put individual age values to its corresponding bins. Here's how to do it:

# a new age value
new_age=30

# use this right=True and '-1' trick to make the bins match
print(np.digitize(new_age, bins=bins, right=True) -1)

my-alpine and docker-compose.yml

 ``` version: '1' services:     man:       build: .       image: my-alpine:latest   ```  Dockerfile: ``` FROM alpine:latest ENV PYTH...