예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
        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
    ]
예제 #7
0
    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