def fit(self, cnx, clients_count, products_count, from_ts, to_ts): # type: (sqlite3.connect, int, int, long, long) -> None # Costruisce le matrici degli ordini self.matrices = {} matrix_shape = (clients_count, products_count) for ts in range(from_ts, to_ts + SECS_IN_DAY, SECS_IN_DAY): self.matrices[ts] = np.zeros(shape=matrix_shape) query = "SELECT datetime, client_id, product_id " \ "FROM orders " \ "WHERE datetime >= %d AND datetime <= %d" % (from_ts, to_ts) cursor = cnx.execute(query) Log.d(TAG, query) for ts, c, p in cursor: key = int(ts) # timestamp dell'ordine assert key in self.matrices.keys() self.matrices[key][int(c), int(p)] = 1 days_count = (to_ts - from_ts + SECS_IN_DAY) / SECS_IN_DAY # Calcola il numero medio di 1 per ogni cella della matrice query = "SELECT count(*) " \ "FROM orders " \ "WHERE datetime >= %d AND datetime <= %d " % (from_ts, to_ts) Log.d(TAG, query) row = cnx.execute(query).fetchone() total_cnt = row[0] avg = float(total_cnt) / float(days_count) avg = int(math.ceil(avg)) self.avg_ones = 1 if avg == 0 else avg return
def __prepare_clients_dataset(cnx, clients_count, from_ts, to_ts): # type: (sqlite3.connect, int, long, long) -> dict """ Crea il dataset per il training dei regressori associati ai cklienti, recuperando i dati dalla connessione al database e per l'intervallo di tempo specificato dai due timestamp. :param cnx: connessione al database da utilizzare :param clients_count: numero di clienti presenti :param from_ts: timestamp relativo al giorno di partenza del dataset :param to_ts: timestamp relativo all'ultimo giorno (incluso) del dataset :return: {(X, y)} dizionario indicizzato per id del cliente contenente le coppie (matrice di train, valori associati) da utilizzare per effettuare il train del relativo regressore """ dfs = {} for c in range(0, clients_count): # Crea il DataFrame con anche le righe per i prodotti non ordinati query = "select datetime, count(*) " \ "from orders " \ "where datetime >= %d and datetime <= %d and client_id = %d " \ "group by datetime, product_id " \ "order by datetime, client_id, product_id" % (from_ts, to_ts, c) Log.d(TAG, query) # ^ ORDER BY è fondamentale per effettuare la creazione in modo efficiente cursor = cnx.execute(query) next_row = cursor.fetchone() df_rows = [] for ts in range(from_ts, to_ts + SECS_IN_DAY, SECS_IN_DAY): ordered = 0 if next_row is not None and next_row[0] == ts: ordered = next_row[1] next_row = cursor.fetchone() order_date = datetime.fromtimestamp(ts) day_of_year = order_date.timetuple().tm_yday year = order_date.timetuple().tm_year df_rows.append({ 'datetime': ts, # timestamp della data dell'ordine 'day_of_year': day_of_year, 'year': year, 'client_id': c, MultiRegressorPredictor.TARGET_COL: ordered }) df = pd.DataFrame( df_rows, columns=MultiRegressorPredictor.CLIENT_TRAIN_COLS + [MultiRegressorPredictor.TARGET_COL]) y = df[MultiRegressorPredictor.TARGET_COL].as_matrix() X = df.drop([MultiRegressorPredictor.TARGET_COL], axis=1).as_matrix() dfs[c] = (X, y) return dfs
def fit(self, cnx, clients_count, products_count, from_ts, to_ts): # type: (sqlite3.connect, int, int, long, long) -> None # Costruisce le matrici degli ordini matrices = {} matrix_shape = (clients_count, products_count) for ts in range(from_ts, to_ts + SECS_IN_DAY, SECS_IN_DAY): matrices[ts] = np.zeros(shape=matrix_shape) query = "SELECT datetime, client_id, product_id " \ "FROM orders " \ "WHERE datetime >= %d AND datetime <= %d" % (from_ts, to_ts) cursor = cnx.execute(query) Log.d(TAG, query) for ts, c, p in cursor: key = int(ts) # timestamp dell'ordine assert key in matrices.keys() matrices[key][int(c), int(p)] = 1 self.pcp_estimation = np.zeros(shape=matrix_shape) self.pp_estimation = np.zeros(shape=(products_count, )) self.pc_estimation = np.zeros(shape=(clients_count, )) ones_cnt = 0 days_count = (to_ts - from_ts + SECS_IN_DAY) / SECS_IN_DAY for day in matrices.keys(): matrix = matrices[day] ones_cnt += matrix.sum() # Media delle righe e delle celle for c in range(0, clients_count): row_avg = matrix[c, :].sum( ) / products_count # numero medio di ordini effetuati dal cliente self.pc_estimation[ c] += row_avg / days_count # lo aggiungo alla media, dividendo già per il totale for p in range(0, products_count): self.pcp_estimation[c, p] += matrix[c, p] / days_count # Media delle colonne for p in range(0, products_count): col_avg = matrix[:, p].sum( ) / clients_count # numero medio di volte che il prodotto è stato ordinato self.pp_estimation[p] += col_avg / days_count # pcp_estimations[c, p] = # medio di volte che il cliente c ha effettuato un ordine del prodotto p # ^ stima di p(c,p) # pp_estimation[p] = media della media delle volte che è stato ordinato il prodotto p # ^ stima di p(p) # pc_estimation[c] = media della media di volte che il cliente c ha effettuato un ordine # ^ stima di p(c) # Calcola il numero giornaliero di ordini medio avg = float(ones_cnt) / float(len(matrices.keys())) avg = int(math.ceil(avg)) self.avg_ones = 1 if avg == 0 else avg return
def __prepare_period_dataset(cnx, from_ts, to_ts): # type: (sqlite3.connect, long, long) -> (np.ndarray, np.ndarray) """ Crea il dataset per il training del regressore del periodo, recuperando i dati dalla connessione al database e per l'intervallo di tempo specificato dai due timestamp. :param cnx: connessione al database da utilizzare :param from_ts: timestamp relativo al giorno di partenza del dataset :param to_ts: timestamp relativo all'ultimo giorno (incluso) del dataset :return: (X, y) matrice delle istanze di train e vettore con i valori associati ad ogni istanza """ # Crea il DataFrame con anche le righe per i prodotti non ordinati query = "select datetime, count(*) " \ "from orders " \ "where datetime >= %d and datetime <= %d " \ "group by datetime " \ "order by datetime" % (from_ts, to_ts) Log.d(TAG, query) # ^ ORDER BY è fondamentale per effettuare la creazione in modo efficiente cursor = cnx.execute(query) next_row = cursor.fetchone() df_rows = [] for ts in range(from_ts, to_ts + SECS_IN_DAY, SECS_IN_DAY): ordered = 0 if next_row is not None and next_row[0] == ts: ordered = next_row[1] next_row = cursor.fetchone() order_date = datetime.fromtimestamp(ts) day_of_year = order_date.timetuple().tm_yday year = order_date.timetuple().tm_year df_rows.append({ 'datetime': ts, # timestamp della data dell'ordine 'day_of_year': day_of_year, 'year': year, MultiRegressorPredictor.TARGET_COL: ordered }) df = pd.DataFrame(df_rows, columns=MultiRegressorPredictor.PERIOD_TRAIN_COLS + [MultiRegressorPredictor.TARGET_COL]) y = df[MultiRegressorPredictor.TARGET_COL].as_matrix() X = df.drop([MultiRegressorPredictor.TARGET_COL], axis=1).as_matrix() return X, y
def fit(self, cnx, clients_count, products_count, from_ts, to_ts): # type: (sqlite3.connect, int, int, long, long) -> None """ Inizializza il predittore recuperando i dati dalla connessione al database :param cnx: connessione al database :param clients_count: numero di clienti :param products_count: numero di prodotti :param from_ts: timestamp del giorno d'inizio dei dati di train :param to_ts: timestamp del giorno finale dei dati di train (incluso) :return: - """ matrix_shape = (clients_count, products_count) self.pcp_estimation = np.zeros(shape=matrix_shape) self.product_regressors = np.ndarray(shape=(products_count, ), dtype=object) self.client_regressors = np.ndarray(shape=(clients_count, ), dtype=object) days_count = (to_ts - from_ts + SECS_IN_DAY) / SECS_IN_DAY # Calcola il numero medio di 1 per ogni cella della matrice total_cnt = 0 query = "select client_id, product_id, count(*) " \ "from orders " \ "where datetime >= %d and datetime <= %d " \ "group by client_id, product_id" % (from_ts, to_ts) Log.d(TAG, query) for c, p, cnt in cnx.execute(query): total_cnt += cnt self.pcp_estimation[c, p] = float(cnt) / float(days_count) avg = float(total_cnt) / float(days_count) avg = int(math.ceil(avg)) self.avg_ones = 1 if avg == 0 else avg # Dati di train per i regressori dei clienti Log.d(TAG, "Fit dei regressori per i clienti...") clients_train_data = self.__prepare_clients_dataset( cnx, clients_count=clients_count, from_ts=from_ts, to_ts=to_ts) for client_id in clients_train_data.keys(): # NOTA: l'id del cliente deve corrispondere con la posizione della matrice X, y = clients_train_data[client_id] self.client_regressors[client_id] = self.__build_clf() self.client_regressors[client_id].fit(X, y) # Dati di train per i regressori dei prodotti Log.d(TAG, "Fit dei regressori per i prodotti...") products_train_data = self.__prepare_products_dataset( cnx, products_count=products_count, from_ts=from_ts, to_ts=to_ts) for product_id in products_train_data.keys(): # NOTA: l'id del prodotto deve corrispondere con la posizione della matrice X, y = products_train_data[product_id] self.product_regressors[product_id] = self.__build_clf() self.product_regressors[product_id].fit(X, y) # Dati di train per il regressore del periodo Log.d(TAG, "Fit del regressore del periodo...") X_period, y_period = self.__prepare_period_dataset(cnx, from_ts=from_ts, to_ts=to_ts) self.period_regressor = self.__build_clf() self.period_regressor.fit(X_period, y_period) return
os.makedirs(OUT_DIR_NAME + "/" + config.base_prefix) load_start_time = time.time() # Dataframe contenti i clienti, prodotti e ordini cnx = sqlite3.connect('./datasets/%s/data/%s.db' % (config.base_prefix, config.base_prefix)) dataset_star_ts = config.starting_day dataset_end_ts = long(dataset_star_ts + (config.days_count - 1) * SECS_IN_DAY) train_set_start_ts = long(dataset_star_ts) train_set_end_ts = long(dataset_end_ts - 7 * SECS_IN_DAY) Log.d(TAG, "Dataset loaded!") Log.d(TAG, "Total duration: " + str(time.time() - load_start_time) + " seconds") ############################ # Test set generation ############################ Log.d(TAG, "Genero le query...") query_ts = [ train_set_end_ts + SECS_IN_DAY, # Giorno immediatamente successivo alla fine del TS train_set_end_ts + 2 * SECS_IN_DAY, # Due giorni dopo la fine del TS train_set_end_ts + 7 * SECS_IN_DAY # Una settimana dopo la fine del TS ]
def fit(self, cnx, clients_count, products_count, from_ts, to_ts): # type: (sqlite3.connect, int, int, long, long) -> None """ Inizializza il predittore recuperando i dati dal database, considerando solamente i dati nell'intervallo temporale specificato (estremi inclusi). :param cnx: connessione al database :param clients_count: numero di clienti :param products_count: numero di prodotti :param from_ts: timestamp del giorno d'inizio dei dati di train :param to_ts: timestamp del giorno finale dei dati di train (incluso) :return: """ self.regressor_matrix = np.ndarray(shape=(clients_count, products_count), dtype=object) days_count = (to_ts - from_ts + SECS_IN_DAY) / SECS_IN_DAY # Calcola il numero medio di 1 per ogni cella della matrice query = "SELECT count(*) " \ "FROM orders " \ "WHERE datetime >= %d AND datetime <= %d " % (from_ts, to_ts) Log.d(TAG, query) row = cnx.execute(query).fetchone() total_cnt = row[0] avg = float(total_cnt) / float(days_count) avg = int(math.ceil(avg)) self.avg_ones = 1 if avg == 0 else avg # df = self.__extract_day_group(dataset) Log.d(TAG, "Fit dei regressori...") for c in range(0, clients_count): for p in range(0, products_count): # Crea il DataFrame con anche le righe per i prodotti non ordinati query = "SELECT datetime " \ "FROM orders " \ "WHERE datetime >= %d " \ "AND datetime <= %d " \ "AND client_id = %d " \ "AND product_id = %d " \ "ORDER BY datetime" % (from_ts, to_ts, c, p) # ^ ORDER BY è fondamentale per effettuare la creazione in modo efficiente Log.d(TAG, query) cursor = cnx.execute(query) next_row = cursor.fetchone() df_rows = [] for ts in range(from_ts, to_ts + SECS_IN_DAY, SECS_IN_DAY): ordered = 0 if next_row is not None and next_row[0] == ts: ordered = 1 next_row = cursor.fetchone() order_date = datetime.fromtimestamp(ts) day_of_year = order_date.timetuple().tm_yday year = order_date.timetuple().tm_year df_rows.append({ 'datetime': ts, # timestamp della data dell'ordine 'day_of_year': day_of_year, 'year': year, SingleRegressorPredictor.TARGET_COL: ordered }) df = pd.DataFrame(df_rows, columns=SingleRegressorPredictor.TRAIN_COLS + [SingleRegressorPredictor.TARGET_COL]) y = df[SingleRegressorPredictor.TARGET_COL].as_matrix() X = df.drop([SingleRegressorPredictor.TARGET_COL], axis=1).as_matrix() clf = None if self.regressor_name == 'SGD': clf = linear_model.SGDRegressor() elif self.regressor_name == 'SVR': clf = SVR() elif self.regressor_name == 'PAR': clf = PassiveAggressiveRegressor() self.regressor_matrix[c, p] = clf self.regressor_matrix[c, p].fit(X, y) return