forked from CherylCB/recommender_python_vs_rust
- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcreate_features_python.py
More file actions
Latest commit
159 lines (119 loc) · 4.91 KB
/
Copy pathcreate_features_python.py
File metadata and controls
159 lines (119 loc) · 4.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
importmath
importnumpyasnp
fromcollectionsimportCounter
importpandasaspd
importdask.dataframeasdd
importdask.arrayasda
NUMBER_OF_TOP_POPULAR_PRODUCTS=6000
MOVING_WINDOW_SIZE=4
REMEMBER_WINDOW_SIZE=4
MOVING_WINDOW_SKIP_SIZE=1
defload_data():
returnpd.read_csv(
"./data/input.csv", encoding="utf-8", dtype=str, na_values="null"
)
defextract_raw_sessions(raw_data):
raw_sessions= []
forxinraw_data["product_sequence"].iteritems():
raw_sessions.append(x[1].split(","))
returnraw_sessions
defget_popular_products(raw_sessions):
products_all_occurrences= [x.strip() foryinraw_sessionsforxinyifx.strip()]
products_ordered_by_occurrences=sorted(
Counter(products_all_occurrences).most_common(NUMBER_OF_TOP_POPULAR_PRODUCTS),
key=lambdax: (x[1], x[0]),
reverse=True,
)
popular_products= [x[0] forxinproducts_ordered_by_occurrences]
returnpopular_products
defcreate_product_ids_masking(popular_products):
return {product: indexforindex, productinenumerate(popular_products)}
defcreate_product_ids_masking_reversed(popular_products):
return {index: productforindex, productinenumerate(popular_products)}
defencode_sessions(product_ids_masking, raw_sessions):
encoded_sessions= [
[
product_ids_masking.get(x)
forxinitem
ifproduct_ids_masking.get(x) isnotNone
]
foriteminraw_sessions
]
returnencoded_sessions
defget_valid_sessions(encoded_sessions):
# Sequence of 1 doesn't have a target ;)
return [xforxinencoded_sessionsiflen(x) >1]
defextract_sequences_vs_targets(encoded_sessions):
# Extract sequences and targets
sequences_vs_targets= []
# Only keep the x latest items that can fit in the REMEMBER_WINDOW_SIZE
number_of_latest_items_to_fetch=MOVING_WINDOW_SIZE+ (
(REMEMBER_WINDOW_SIZE-1) *MOVING_WINDOW_SKIP_SIZE
)
forsessioninencoded_sessions:
targets=session[1:]
intervals= []
forindex, targetinenumerate(targets):
base=session[: index+1][-number_of_latest_items_to_fetch:]
len_base_minus_window_size=len(base) -REMEMBER_WINDOW_SIZE
number_of_active_remember_windows= (
math.ceil(len_base_minus_window_size/MOVING_WINDOW_SKIP_SIZE) +1
)
ifnumber_of_active_remember_windows<1:
number_of_active_remember_windows=1
sequences= [
base[i : i+MOVING_WINDOW_SIZE]
foriinrange(number_of_active_remember_windows)
]
sequences= ([[]] * (REMEMBER_WINDOW_SIZE-len(sequences))) +sequences
intervals.append(sequences)
sequences_vs_targets.append([intervals, targets])
# print(sequences_vs_targets)
returnsequences_vs_targets
defencode_binary(sequences_vs_targets):
# binary encoding
OUTPUT_PROCESSING_CHUNK_SIZE=10000
number_of_sequences=len(sequences_vs_targets)
chunks= [
sequences_vs_targets[x : x+OUTPUT_PROCESSING_CHUNK_SIZE]
forxinrange(0, number_of_sequences, OUTPUT_PROCESSING_CHUNK_SIZE)
]
forcount, sequences_targets_slicedinenumerate(chunks):
combined_X= []
combined_y= []
forX, yinsequences_targets_sliced:
number_items=len(X)
X_=np.zeros(
(number_items, MOVING_WINDOW_SIZE, NUMBER_OF_TOP_POPULAR_PRODUCTS),
dtype=bool,
)
y_=np.zeros((number_items, NUMBER_OF_TOP_POPULAR_PRODUCTS), dtype=bool)
forindex, (x_indexes, y_index) inenumerate(zip(X, y)):
y_[index][y_index] =1
forinterval_indexinrange(MOVING_WINDOW_SIZE):
X_[index][interval_index][x_indexes[interval_index]] =1
combined_X.append(np.copy(X_))
combined_y.append(np.copy(y_))
delX_
dely_
dataset_X=np.vstack(combined_X)
dataset_y=np.vstack(combined_y)
returndataset_X, dataset_y
defmain():
raw_data=load_data()
print(raw_data.head())
raw_sessions=extract_raw_sessions(raw_data)
popular_products=get_popular_products(raw_sessions)
popular_products_encoded=list(range(NUMBER_OF_TOP_POPULAR_PRODUCTS))
product_ids_masking=create_product_ids_masking(popular_products)
product_ids_masking_reversed=create_product_ids_masking_reversed(popular_products)
# encoding
encoded_sessions=encode_sessions(product_ids_masking, raw_sessions)
encoded_sessions=get_valid_sessions(encoded_sessions)
sequences_vs_targets=extract_sequences_vs_targets(encoded_sessions)
X, y=encode_binary(sequences_vs_targets)
print(f"length of X and y: {len(X)}, {len(y)}")
print("end")
returnX, y
if__name__=="__main__":
main()