-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRating Prediction Project Code.cpp
More file actions
143 lines (110 loc) · 4.59 KB
/
Copy pathRating Prediction Project Code.cpp
File metadata and controls
143 lines (110 loc) · 4.59 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
// Kendime Not: Data sorted olduðu için Nested map kullandým. <user , <item , rating >>
// ITR similarity ve User Based CF kullandým.
#include <iostream>
#include <map>
#include <cmath>
#include <vector>
#include <sstream>
#include <iomanip>
#include <algorithm>
using namespace std;
using OrderedMap = map<int, map<int, double>>; // NestedMap tarifi
OrderedMap train_data_set; // My nestedmap name
// ITR similarity calculation
double ITRSimilarity(int user1, int user2) {
const auto& ratings1 = train_data_set.at(user1); // ratings1 = <item , rating > for user 1
const auto& ratings2 = train_data_set.at(user2);
double mean1 = 0.0, mean2 = 0.0;
for (const auto& r : ratings1) mean1 += r.second; // r = ratings1 -- r.first = itemID --- r.second = rating
mean1 /= ratings1.size();
for (const auto& r : ratings2) mean2 += r.second;
mean2 /= ratings2.size();
double sigma_ust1 = 0.0, sigma_ust2 = 0.0;
for (const auto& r : ratings1) {
sigma_ust1 += pow(r.second - mean1, 2);
}
double sigma1 = sqrt(sigma_ust1 / ratings1.size());
for (const auto& r : ratings2) {
sigma_ust2 += pow(r.second - mean2, 2);
}
double sigma2 = sqrt(sigma_ust2 / ratings2.size());
double tri_ust = 0.0;
double tri_alt1 = 0.0;
double tri_alt2 = 0.0;
for (const auto& pair : ratings1) {
int itemID = pair.first;
tri_alt1 += pow(pair.second, 2);
if (ratings2.find(itemID) != ratings2.end()) {
tri_ust += pow(pair.second - ratings2.at(itemID), 2);
}
}
for (const auto& pair : ratings2) {
tri_alt2 += pow(pair.second, 2);
}
double tri_alt = sqrt(tri_alt1) + sqrt(tri_alt2);
if (tri_alt == 0) return 0.0;
double simTRIANGLE = 1 - (sqrt(tri_ust) / tri_alt);
double urp = 1 - 1 / (1 + exp(-fabs(mean1 - mean2) * fabs(sigma1 - sigma2)));
return simTRIANGLE * urp; // ITR function returns to this value
}
// PREDICT RATING WITH UBCF
double UBCF_PredictRating(int user, int item, int k) {
vector<pair<double, int>> neighbors; // Created Neighbor vector
for (const auto& otherUser : train_data_set) {
int otherUserId = otherUser.first;
if (user == otherUserId) continue; // If its itself it will skip
if (otherUser.second.find(item) != otherUser.second.end()) { //Making sure targetitem exist. If find item == end it means there is no targetitem in there
double similarity = ITRSimilarity(user, otherUserId);
if (similarity > 0.3) neighbors.emplace_back(similarity, otherUserId); // Insert the element at the end of the neighbors vector And similarity THRESHOLD***
}
}
sort(neighbors.rbegin(), neighbors.rend()); // Worst and Avg time complx. O(nlogn) . Sorts the vector in decending order.
double ubcf_ust = 0.0, ubcf_alt = 0.0;
for (int i = 0; i < min(k, (int)neighbors.size()); ++i) { // its like we are saying [top k , neighbor] stay in this and loop top k time
double similarity = neighbors[i].first; // assigns the pair<neighbor,userýd> at i and with .first , its the similarity at i
int neighborId = neighbors[i].second;
double rating = train_data_set[neighborId][item];
ubcf_ust += similarity * rating;
ubcf_alt += fabs(similarity);
}
return (ubcf_alt == 0.0) ? 0.0 : (ubcf_ust / ubcf_alt); // IF denom is 0.0 then return 0.0 . IF not the other part
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
string line;
bool isTest = false;
vector<pair<int, int>> testPairs;
while (getline(cin, line)) {
if (line == "train dataset") {
isTest = false;
continue;
}
else if (line == "test dataset") {
isTest = true;
continue;
}
stringstream ss(line);
int userId, itemId;
double rating;
if (isTest) {
ss >> userId >> itemId;
testPairs.emplace_back(userId, itemId);
}
else {
ss >> userId >> itemId >> rating;
train_data_set[userId][itemId] = rating; // LOADS MY MAP
}
}
int k = 50; //TOP K
for (const auto& testPair : testPairs) { // test pair contains <userýd , itemýd >
int userId = testPair.first;
int itemId = testPair.second;
double prediction = 0.0;
if (train_data_set.find(userId) != train_data_set.end()) { // If target user exists in my train_data_set map
prediction = UBCF_PredictRating(userId, itemId, k);
}
cout << fixed << setprecision(2) << prediction << endl;
}
return 0;
}