-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.py
More file actions
167 lines (154 loc) · 6.47 KB
/
Copy pathutils.py
File metadata and controls
167 lines (154 loc) · 6.47 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
160
161
162
163
164
165
166
167
## some utility functions
import csv, jsonlines
import os
import sys
import numpy as np
import copy
import random
def load_csv_data(filename, delimiter, verbose=True):
"""
input: a file readable as csv and separated by a delimiter
and has format users - movies - ratings - etc
output: a list, where each row of the list is of the form
{'in0':userID, 'in1':movieID, 'label':rating}
"""
to_data_list = list()
users = list()
movies = list()
ratings = list()
unique_users = set()
unique_movies = set()
with open(filename, 'r') as csvfile:
reader = csv.reader(csvfile, delimiter=delimiter)
for count, row in enumerate(reader):
#if count!=0:
to_data_list.append({'in0':[int(row[0])], 'in1':[int(row[1])], 'label':float(row[2])})
users.append(row[0])
movies.append(row[1])
ratings.append(float(row[2]))
unique_users.add(row[0])
unique_movies.add(row[1])
if verbose:
print("In file {}, there are {} ratings".format(filename, len(ratings)))
print("The ratings have mean: {}, median: {}, and variance: {}".format(
round(np.mean(ratings), 2),
round(np.median(ratings), 2),
round(np.var(ratings), 2)))
print("There are {} unique users and {} unique movies".format(len(unique_users), len(unique_movies)))
return to_data_list
def csv_to_augmented_data_dict(filename, delimiter):
"""
Input: a file that must be readable as csv and separated by delimiter (to make columns)
has format users - movies - ratings - etc
Output:
Users dictionary: keys as user ID's; each key corresponds to a list of movie ratings by that user
Movies dictionary: keys as movie ID's; each key corresponds a list of ratings of that movie by different users
"""
to_users_dict = dict()
to_movies_dict = dict()
with open(filename, 'r') as csvfile:
reader = csv.reader(csvfile, delimiter=delimiter)
for count, row in enumerate(reader):
#if count!=0:
if row[0] not in to_users_dict:
to_users_dict[row[0]] = [(row[1], row[2])]
else:
to_users_dict[row[0]].append((row[1], row[2]))
if row[1] not in to_movies_dict:
to_movies_dict[row[1]] = list(row[0])
else:
to_movies_dict[row[1]].append(row[0])
return to_users_dict, to_movies_dict
def user_dict_to_data_list(user_dict):
# turn user_dict format to data list format (acceptable to the algorithm)
data_list = list()
for user, movie_rating_list in user_dict.items():
for movie, rating in movie_rating_list:
data_list.append({'in0':[int(user)], 'in1':[int(movie)], 'label':float(rating)})
return data_list
def divide_user_dicts(user_dict, sp_ratio_dict):
"""
Input: A user dictionary, a ration dictionary
- format of sp_ratio_dict = {'train':0.8, "test":0.2}
Output:
A dictionary of dictionaries, with key corresponding to key provided by sp_ratio_dict
and each key corresponds to a subdivded user dictionary
"""
ratios = [val for _, val in sp_ratio_dict.items()]
assert np.sum(ratios) == 1, "the sampling ratios must sum to 1!"
divided_dict = {}
for user, movie_rating_list in user_dict.items():
sub_movies_ptr = 0
sub_movies_list = []
#movie_list, _ = zip(*movie_rating_list)
#print(movie_list)
for i, ratio in enumerate(ratios):
if i < len(ratios)-1:
sub_movies_ptr_end = sub_movies_ptr + int(len(movie_rating_list)*ratio)
sub_movies_list.append(movie_rating_list[sub_movies_ptr:sub_movies_ptr_end])
sub_movies_ptr = sub_movies_ptr_end
else:
sub_movies_list.append(movie_rating_list[sub_movies_ptr:])
for subset_name in sp_ratio_dict.keys():
if subset_name not in divided_dict:
divided_dict[subset_name] = {user: sub_movies_list.pop(0)}
else:
#access sub-dictionary
divided_dict[subset_name][user] = sub_movies_list.pop(0)
return divided_dict
def write_csv_to_jsonl(jsonl_fname, csv_fname, csv_delimiter):
"""
Input: a file readable as csv and separated by delimiter (to make columns)
- has format users - movies - ratings - etc
Output: a jsonline file converted from the csv file
"""
with jsonlines.open(jsonl_fname, mode='w') as writer:
with open(csv_fname, 'r') as csvfile:
reader = csv.reader(csvfile, delimiter=csv_delimiter)
for count, row in enumerate(reader):
#print(row)
#if count!=0:
writer.write({'in0':[int(row[0])], 'in1':[int(row[1])], 'label':float(row[2])})
print('Created {} jsonline file'.format(jsonl_fname))
def write_data_list_to_jsonl(data_list, to_fname):
"""
Input: a data list, where each row of the list is a Python dictionary taking form
{'in0':userID, 'in1':movieID, 'label':rating}
Output: save the list as a jsonline file
"""
with jsonlines.open(to_fname, mode='w') as writer:
for row in data_list:
#print(row)
writer.write({'in0':row['in0'], 'in1':row['in1'], 'label':row['label']})
print("Created {} jsonline file".format(to_fname))
def data_list_to_inference_format(data_list, binarize=True, label_thres=3):
"""
Input: a data list
Output: test data and label, acceptable by SageMaker for inference
"""
data_ = [({"in0":row['in0'], 'in1':row['in1']}, row['label']) for row in data_list]
data, label = zip(*data_)
infer_data = {"instances":data}
if binarize:
label = get_binarized_label(list(label), label_thres)
return infer_data, label
def get_binarized_label(data_list, thres):
"""
Input: data list
Output: a binarized data list for recommendation task
"""
for i, row in enumerate(data_list):
if type(row) is dict:
#if i < 10:
#print(row['label'])
if row['label'] > thres:
#print(row)
data_list[i]['label'] = 1
else:
data_list[i]['label'] = 0
else:
if row > thres:
data_list[i] = 1
else:
data_list[i] = 0
return data_list