utils.py 9.51 KB
Newer Older
1
# encoding = "utf-8"
张彦钊's avatar
张彦钊 committed
2 3
from datetime import datetime
from datetime import timedelta
4 5
import pymysql
import numpy as np
张彦钊's avatar
张彦钊 committed
6 7 8 9
import pandas as pd
from sklearn import metrics
from sklearn.metrics import auc
from multiprocessing import Pool
张彦钊's avatar
张彦钊 committed
10
import os
11
import signal
12
from config import *
张彦钊's avatar
张彦钊 committed
13 14
import socket

张彦钊's avatar
张彦钊 committed
15

张彦钊's avatar
张彦钊 committed
16 17 18 19 20
def judge_online():
    # 下面这个ip是本地电脑ip
    if socket.gethostbyname(socket.gethostname()) == '172.30.8.160':
        flag = False
        path = LOCAL_DIRCTORY
张彦钊's avatar
张彦钊 committed
21 22 23 24
    else:
        flag = True
        path = DIRECTORY_PATH
    return flag,path
张彦钊's avatar
张彦钊 committed
25

26

张彦钊's avatar
张彦钊 committed
27 28 29 30 31 32
def get_date():
    now = datetime.now()
    year = now.year
    month = now.month
    day = now.day
    date = datetime(year,month,day)
33
    data_start_date = "2018-07-15"
34 35
    # data_end_date = "2018-09-02"
    # validation_date = "2018-09-01"
36
    # data_start_date = (date - timedelta(days=3)).strftime("%Y-%m-%d")
37 38
    data_end_date = (date - timedelta(days=1)).strftime("%Y-%m-%d")
    validation_date = (date - timedelta(days=2)).strftime("%Y-%m-%d")
张彦钊's avatar
张彦钊 committed
39
    # 验证集和测试集的日期必须相差一天,否则切割数据集时会报错
张彦钊's avatar
张彦钊 committed
40 41 42 43 44 45
    test_date = data_end_date
    print("data_start_date,data_end_date,validation_date,test_date:")
    print(data_start_date,data_end_date,validation_date,test_date)
    return data_start_date,data_end_date,validation_date,test_date


张彦钊's avatar
张彦钊 committed
46 47 48 49 50 51 52 53
def get_roc_curve(y, pred, pos_label):
    """
    计算二分类问题的roc和auc
    """
    fpr, tpr, thresholds = metrics.roc_curve(y, pred, pos_label)
    AUC = metrics.auc(fpr, tpr)
    print(AUC)

54

张彦钊's avatar
张彦钊 committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
# 从Tidb数据库的表里获取数据,并转化成df格式,去掉空值
def con_sql(db,sql):
    cursor = db.cursor()
    try:
        cursor.execute(sql)
        result = cursor.fetchall()
        df = pd.DataFrame(list(result)).dropna()
    except Exception:
        print("发生异常", Exception)
        df = pd.DataFrame()
    finally:
        db.close()
    return df


# 下面这个函数与上面那个函数区别是上面那个函数去掉了空值
def sql_df(db,sql):
72
    cursor = db.cursor()
张彦钊's avatar
张彦钊 committed
73 74 75 76 77 78 79 80 81
    try:
        cursor.execute(sql)
        result = cursor.fetchall()
        df = pd.DataFrame(list(result))
    except Exception:
        print("发生异常", Exception)
        df = pd.DataFrame()
    finally:
        db.close()
张彦钊's avatar
张彦钊 committed
82
    return df
83

张彦钊's avatar
张彦钊 committed
84

张彦钊's avatar
张彦钊 committed
85
def move_file():
86
    import os
87
    for eachFile in os.listdir(DIRECTORY_PATH+"train"):
88
        os.rename(DIRECTORY_PATH+"train" + "/" + eachFile,DIRECTORY_PATH + eachFile)
89
    print("成功将文件剪切到对应路径")
张彦钊's avatar
张彦钊 committed
90 91


92
def restart_process():
93
    out = os.popen("ps aux | grep diaryUpdateOnlineOffline.py").read()
94
    for line in out.splitlines():
95
        if 'python diaryUpdateOnlineOffline.py' in line:
96
            pid = int(line.split()[1])
97 98 99
            # 有些进程的生命周期非常短或者随时可能结束,一定要捕捉这个异常
            try:
                os.kill(pid, signal.SIGKILL)
100
                print("已杀死python diaryUpdateOnlineOffline.py 进程")
101 102
            except OSError:
                print('没有如此进程!!!')
103
            os.popen('python diaryUpdateOnlineOffline.py')
张彦钊's avatar
张彦钊 committed
104
            print("已经成功重启diaryUpdateOnlineOffline.py")
105
        else:
106 107
            os.popen('python diaryUpdateOnlineOffline.py')
            print("成功重启diaryUpdateOnlineOffline.py")
108

张彦钊's avatar
张彦钊 committed
109

张彦钊's avatar
张彦钊 committed
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
# 多线程ffm转化类:
class multiFFMFormatPandas:
    def __init__(self):
        self.field_index_ = None
        self.feature_index_ = None
        self.y = None

    def fit(self, df, y=None):
        self.y = y
        df_ffm = df[df.columns.difference([self.y])]
        if self.field_index_ is None:
            self.field_index_ = {col: i for i, col in enumerate(df_ffm)}

        if self.feature_index_ is not None:
            last_idx = max(list(self.feature_index_.values()))

        if self.feature_index_ is None:
            self.feature_index_ = dict()
            last_idx = 0

        for col in df.columns:
            vals = df[col].unique()
            for val in vals:
                if pd.isnull(val):
                    continue
                name = '{}_{}'.format(col, val)
                if name not in self.feature_index_:
                    self.feature_index_[name] = last_idx
                    last_idx += 1
            self.feature_index_[col] = last_idx
            last_idx += 1

        return self

张彦钊's avatar
张彦钊 committed
144
    def fit_transform(self, df, y=None,n=50000,processes=4):
张彦钊's avatar
张彦钊 committed
145 146 147 148
        # n是每个线程运行最大的数据条数,processes是线程数
        self.fit(df, y)
        n = n
        processes = processes
149
        return self.transform(df,n,processes)
张彦钊's avatar
张彦钊 committed
150 151 152 153 154 155 156 157 158 159 160 161

    def transform_row_(self, row, t):
        ffm = []
        if self.y is not None:
            ffm.append(str(row.loc[row.index == self.y][0]))
        if self.y is None:
            ffm.append(str(0))

        for col, val in row.loc[row.index != self.y].to_dict().items():
            col_type = t[col]
            name = '{}_{}'.format(col, val)
            if col_type.kind == 'O':
张彦钊's avatar
张彦钊 committed
162
                ffm.append('{}:{}:1'.format(self.field_index_[col]+1, self.feature_index_[name]+1))
张彦钊's avatar
张彦钊 committed
163
            elif col_type.kind == 'i':
张彦钊's avatar
张彦钊 committed
164
                ffm.append('{}:{}:{}'.format(self.field_index_[col]+1, self.feature_index_[col]+1, val))
张彦钊's avatar
张彦钊 committed
165 166
        return ' '.join(ffm)

167
    def transform(self, df,n=1500,processes=2):
张彦钊's avatar
张彦钊 committed
168 169 170 171 172
        # n是每个线程运行最大的数据条数,processes是线程数
        t = df.dtypes.to_dict()
        data_list = self.data_split_line(df,n)

        # 设置进程的数量
173
        pool = Pool(processes)
张彦钊's avatar
张彦钊 committed
174
        print("总进度: " + str(len(data_list)))
张彦钊's avatar
张彦钊 committed
175 176 177
        for i in range(len(data_list)):
            data_list[i] = pool.apply_async(self.pool_function, (data_list[i], t,))

张彦钊's avatar
张彦钊 committed
178 179 180
        result_map = {}
        for i in data_list:
            result_map.update(i.get())
张彦钊's avatar
张彦钊 committed
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
        pool.close()
        pool.join()

        return pd.Series(result_map)

    # 多进程计算方法
    def pool_function(self, df, t):
        return {idx: self.transform_row_(row, t) for idx, row in df.iterrows()}

    # 切分数据方法,传人dataframe和切分条数的步长,返回dataframe的集合,每个dataframe中含有若干条数据
    def data_split_line(self, data, step):
        data_list = []
        x = 0
        while True:
            if x + step < data.__len__():
                data_list.append(data.iloc[x:x + step])
                x = x + step + 1
            else:
                data_list.append(data.iloc[x:data.__len__()])
                break

        '''
        # 返回生成器方法,但是本地测试效率不高
        x = 0
        while True:
            if x + step < data.__len__():
                yield data.iloc[x:x + step]
                x = x + step + 1
            else:
                yield data.iloc[x:data.__len__()]
                break
        '''

        return data_list

216 217 218 219 220
    # 原生转化方法,不需要多进程
    def native_transform(self, df):
            t = df.dtypes.to_dict()
            return pd.Series({idx: self.transform_row_(row, t) for idx, row in df.iterrows()})

张彦钊's avatar
张彦钊 committed
221 222 223 224 225 226 227

    # 下面这个方法不是这个类原有的方法,是新增的。目的是用来判断这个用户是不是在训练数据集中存在
    def is_feature_index_exist(self, name):
        if name in self.feature_index_:
            return True
        else:
            return False
228

229
# ffm 格式转换函数、类
张彦钊's avatar
张彦钊 committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
# class FFMFormatPandas:
#     def __init__(self):
#         self.field_index_ = None
#         self.feature_index_ = None
#         self.y = None
#
#     def fit(self, df, y=None):
#         self.y = y
#         df_ffm = df[df.columns.difference([self.y])]
#         if self.field_index_ is None:
#             self.field_index_ = {col: i for i, col in enumerate(df_ffm)}
#
#         if self.feature_index_ is not None:
#             last_idx = max(list(self.feature_index_.values()))
#
#         if self.feature_index_ is None:
#             self.feature_index_ = dict()
#             last_idx = 0
#
#         for col in df.columns:
#             vals = df[col].unique()
#             for val in vals:
#                 if pd.isnull(val):
#                     continue
#                 name = '{}_{}'.format(col, val)
#                 if name not in self.feature_index_:
#                     self.feature_index_[name] = last_idx
#                     last_idx += 1
#             self.feature_index_[col] = last_idx
#             last_idx += 1
#         return self
#
#     def fit_transform(self, df, y=None):
#         self.fit(df, y)
#         return self.transform(df)
#
#     def transform_row_(self, row, t):
#         ffm = []
#         if self.y is not None:
#             ffm.append(str(row.loc[row.index == self.y][0]))
#         if self.y is None:
#             ffm.append(str(0))
#
#         for col, val in row.loc[row.index != self.y].to_dict().items():
#             col_type = t[col]
#             name = '{}_{}'.format(col, val)
#             if col_type.kind == 'O':
#                 ffm.append('{}:{}:1'.format(self.field_index_[col], self.feature_index_[name]))
#             elif col_type.kind == 'i':
#                 ffm.append('{}:{}:{}'.format(self.field_index_[col], self.feature_index_[col], val))
#         return ' '.join(ffm)
#
#     def transform(self, df):
#         t = df.dtypes.to_dict()
#         return pd.Series({idx: self.transform_row_(row, t) for idx, row in df.iterrows()})
#
张彦钊's avatar
张彦钊 committed
286
#     下面这个方法不是这个类原有的方法,是新增的。目的是用来判断这个用户是不是在训练数据集中存在
张彦钊's avatar
张彦钊 committed
287 288 289 290 291
#     def is_feature_index_exist(self, name):
#         if name in self.feature_index_:
#             return True
#         else:
#             return False