A. User-Item Approach
1)it requires training
2) it requires massive data to store
User * Features + Item * Features
3) it gets really expensive when it get’s big
O(user * item)
User의 ItemA에 대한예상 점수
= AVG(User가 이미 평가한 ItemB의 점수 * ItemB와 ItemA의 유사도 점수)
User의 ItemA에 대한 예상 점수 ( “Like” 만 있을때 )
= AVG(User가 좋아한 ItemB와 ItemA의 유사도 점수)
내가 A, B를 Like했고, S(A, C) = 0.5, S(B, C) = 0.8 이면,
나의 C에 대한 예상 점수 = (0.5 + 0.8) / 2 = 0.65
14.
장점
1)User-Item Rating, Item-ItemSimilarity 두개만 관리하면되서,
사이즈가 훨씬 작음.
(특히, Item 갯수가 User 갯수에 비해 작을땐)
2)자연스럽게 Item-Item Similarity를 알게 되기 때문에,
"요 Item의 Related Items..." 를 일석이조
Interest-Interest score
WITH
interest_reads AS(
SELECT
user_id,
content_id as interest
FROM user_actions
WHERE
(year || month || day) >
date_format(CURRENT_TIMESTAMP - interval '30' DAY, '%Y%m%d')
GROUP BY 1, 2
),
ab_inner_reads_count AS (
SELECT
a.interest AS a,
b.interest AS b,
count(1) AS count
FROM interest_reads a
JOIN interest_reads b ON a.user_id = b.user_id AND a.interest < b.interest
GROUP BY 1, 2
),
reads_count AS (
SELECT
interest, count(1) AS count
FROM interest_reads
GROUP BY 1
),
similarity AS (
SELECT
innerCnt.a AS a,
innerCnt.b AS b,
(innerCnt.count / (aCount.count + bCount.count - innerCnt.count)) AS score
FROM ab_inner_reads_count AS innerCnt
JOIN reads_count AS aCount ON aCount.interest = innerCnt.a
JOIN reads_count AS bCount ON bCount.interest = innerCnt.b
)
SELECT * FROM similarity
[user_id, interest]
[A, count]
[A, B, count]
To avoid [B, A, count], a < b
[A, B, count] JOIN [A, count] JOIN [B, count]
[A, B, score]
(year || month|| day) >
date_format(CURRENT_TIMESTAMP - interval '30' DAY, '%Y%m%d')
GROUP BY 1, 2
),
ab_inner_reads_count AS (
SELECT
a.interest AS a,
b.interest AS b,
count(1) AS count
FROM interest_reads a
JOIN interest_reads b ON a.user_id = b.user_id AND a.interest < b.interest
GROUP BY 1, 2
),
reads_count AS (
SELECT
interest, count(1) AS count
FROM interest_reads
GROUP BY 1
),
similarity AS (
SELECT
innerCnt.a AS a,
innerCnt.b AS b,
(innerCnt.count / (aCount.count + bCount.count - innerCnt.count)) AS score
FROM ab_inner_reads_count AS innerCnt
JOIN reads_count AS aCount ON aCount.interest = innerCnt.a
JOIN reads_count AS bCount ON bCount.interest = innerCnt.b
)
SELECT
a,
json_format(
CAST(
array_agg(
ROW(b, score)
) AS JSON
)
) as cards
FROM similarity
GROUP BY 1
[A, "[[B, 0.1], [C, 0.2]....]"]
[B, "[[C, 0.1], [D, 0.2]....]"]
30.
LOAD DATA FROMS3 's3://vingle-redshift/athena_output.csv'
REPLACE
INTO TABLE interest_similarity
CHARACTER SET 'utf8mb4'
FIELDS
TERMINATED BY ','
ENCLOSED BY '"'
IGNORE 1 ROWS (@interest, @others)
SET
interest = @interest,
others = @others,
created_at = CURRENT_TIMESTAMP;
CREATE TABLE `interest_similarity` (
`interest` VARCHAR(50) NOT NULL,
`others` text COLLATE utf8mb4_bin NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`interest`)
)
Aurora로 Load!
User-Recently-Visited-Interest
WITH
interest_reads AS (
SELECT
session_data.user_id,
data.content.idas interest
FROM track_tickets.user_content_action
WHERE
(year || month || day) > date_format(CURRENT_TIMESTAMP - interval '30' DAY, '%Y%m%d')
GROUP BY
1, 2
)
SELECT
user_id,
json_format(CAST(array_agg(ROW(interest)) AS JSON)) as interests
FROM interest_reads
GROUP BY 1
[user_id, "[['A'], ['B'], ....]"]
33.
LOAD DATA FROMS3 's3://vingle-redshift/athena_output.csv'
REPLACE
INTO TABLE user_interest
CHARACTER SET 'utf8mb4'
FIELDS
TERMINATED BY ','
ENCLOSED BY '"'
IGNORE 1 ROWS (@user_id, @others)
SET
user_id = @user_id,
others = @others,
created_at = CURRENT_TIMESTAMP;
CREATE TABLE `user_interest` (
`user_id` INT NOT NULL,
`others` text COLLATE utf8mb4_bin NOT NULL,
`created_at` datetime NOT NULL,
PRIMARY KEY (`user_id`)
)
Aurora로 Load!