9health / moviegeek

A django website used in the book Practical Recommender Systems to illustrate how recommender algorithms can be implemented.
MIT License
0 stars 0 forks source link

Peruse (read something in a relaxed way) PRS book #10

Open 9health opened 1 year ago

9health commented 1 year ago

Output

Reason

History

9health commented 1 year ago

Hello @quangvv9Life,

Về buổi nói chuyện hôm Thứ 7

Thanks Quang và anh Công hôm trước T7 đã cùng nghe Hải nói về đọc PRS và khó khăn gặp phải nhé.

Như tớ đã nói thì tớ cũng không giỏi lắm phần thuật toán.

Ví dụ như ở Chương 7 có những thuật toán hay phương pháp sau

7.2 Essential similarity functions
  7.2.1 Jaccard distance
  7.2.2 Lo-norms
  7.2.3 Cosine similarity
  7.2.4 Pearson Similarity
  7.2.5 Test running Pearson Similarity
  7.2.6 Pearson is really similar to cosine

Rồi tớ cũng feedback là cũng đọc qua Chương 9 nhưng mà nói thật cũng sợ đọc xong hơi hiểu hiểu thôi, không làm thì quên mất =.=

Anh Công với Quang cũng góp ý là nên vừa đọc vừa làm...

Tớ cũng đồng ý với cái đấy.

Có lẽ cứ đọc xong cái gì có 1 đoạn code ra được thì sẽ nhớ nhất!!!

Mà không biết sẽ khó khăn thế nào nữa đây hix...

Về việc Quang đề nghị giúp đỡ tớ

Thì Quang cũng có nói là Quang tuần này sẽ bắt đầu nghỉ ở MB.

Quang cũng có nhiều thời gian hơn và có thể giúp tớ mấy chỗ khó bằng cách đọc lại T_T

Rồi chắc Quang sẽ giảng lại cho tớ nhỉ T_T.

Phản ứng ban đầu của tớ thì cũng là không muốn vì thực ra tớ nghĩ đọc xong giải thích cho người khác cũng khó hix.

Hình như tớ không quen tiếp nhận sự giúp đỡ người khác 1 cách trực tiếp như thế. Thói quen mà hix.

Sau về nhà tớ cũng nghĩ thêm liệu có thể nhờ Quang gì được đây T_T

Có lẽ tớ không dám chắc lắm nhưng mà khả năng chắc nhờ Quang check hộ log chạy cái website trên server =.=

Tớ cũng nghĩ sẽ có những cái log khá khó đấy nhưng mà hi vọng Quang fix được hết hoặc 1 phần thui cũng được =.=

Còn tớ tập trung quyển sách kia xem sao.

Tớ thấy như thế hợp lý hơn. Hi vọng Quang chấp nhận!!! Vì dù sao như Quang nói hình như cái web app chạy lên rồi mà có vẻ chưa ra đúng, chưa thấy recommendation đâu hix.

Về thời gian biểu tớ hôm nay

Mấy hôm nay hình như tớ toàn dậy sớm thì phải.

Sáng CN thì dậy từ 5 giờ hơn hay 6 giờ để đi bốc mộ bà em ông ngoại tớ ở quê Hà Tây @@. Đi từ nhà dì thôi, cách nhà dì khoảng 30 phút.

Sáng nay thì dậy sớm 6 giờ để đến trường THCS Nguyễn Trãi giúp mẹ quay video ca nhạc biểu diễn kỷ niệm 22/12 cho các em học sinh xem ý @@.

Vậy là chiều nay 3 giờ 30 chiều mới mò dậy được hix. Mẹ tớ cũng mệt hay sao mà chả quát dậy nữa @@.

Sáng nay thì vì biết (hơi biết thôi) là mẹ sẽ gọi mình đi sớm rồi. Tối CN mẹ tớ chỉ nói sáng hôm sau con đi với mẹ mà chả nói thời gian là gì :( Tớ cũng chả buồn hỏi lại 😞. Tính tớ thế mà =.=

Vậy là sáng nay nghĩ mãi nên đọc sách PRS, nên kiểm tra log hay làm gì nhỉ _TT.

Cuối cùng 9h sáng cũng về rồi vì tới 8h30 là hết chương trình, tớ chọn thôi đọc Chương 1 miễn phí trên ý cho dễ =.=

Nguyên nhân là vì hôm nay mệt mà cứ đâm đầu làm cái khó chắc kết quả cũng chả có gì cả...

Haizzz.

Về Chương 1 sách PRS

Lúc tớ đọc Chương 1 thì thấy tác giả cũng viết nhiều, cũng reference nhiều thứ nhưng mà Netflix là chủ yếu ấy 😢.

Tớ cũng đọc những link tác giả reference.

Tớ ấn tượng với hệ thống 600 màn hình có thể customize theo giới tính, tuổi người xem ở 1 sân bay Đan Mạch thôi hix.

Chứ vào link Netflix blog nói về hệ thống recommendation của họ lại thấy chóng mặt =.=

https://netflixtechblog.com/netflix-recommendations-beyond-the-5-stars-part-1-55838468f429

Có vẻ cái này nó không vào tớ được. Nó thiên về cảm giác chủ quan, thiên về kiểu con người quá T_T.

Thôi đành cố vậy @@@@@@.

Rồi những phần khác đọc cũng thấy hơi mơ hồ 1 xíu. Có lẽ đo chương đấy là Overview mà.

Tớ túm lại cũng hiểu sơ sơ thôi, chưa thấy code, chưa chạy được xem vào ra thế nào thì vẫn chưa thực sự là hiểu ý :(

Nói thật cảm giác hôm trước tớ đọc phần phỏng vấn tác giả có vẻ vào hơn =.=

Thôi thì cứ tiếp tục nào. Có lẽ do hôm nay còn hơi mệt =.=

Hi vọng mai sẽ khấm khá hơn, ra cái gì đó hay ho hơn.

Tớ dùng 10h sáng tới 12h sáng để đọc Chương 1 và 1 ít link reference hix.

15h30 dậy thì ngồi update nốt file nói về tương lai và ghi nhận cảm xúc vì ăn uống, vì nói chuyện nhiều thứ quá hix.

Làm tới 18h30 thì xong.

Giờ tớ đang viết cho Quang comment đây!!!

Cảm ơn Quang đã đọc đến đây.

Chúc Quang buổi tối vui vẻ!!!

9health commented 1 year ago

Hello @quangvv9Life,

Thanks Quang đã fix lỗi bên M365 nhé @@. Tớ vẫn chưa check comment bên đấy hix

Không hiểu sao vẫn chưa có notification lúc đăng nhập GitHub trên Safari ở macOS =.= Hay Quang quên mention @9Health nhỉ =.=

Về Chương 2 tớ đọc hôm nay

Hôm nay tớ có vào link xem Chương 2 của quyển PRS ở Manning thì cũng có nhiều cảm giác khá hay ho.

https://livebook.manning.com/book/practical-recommender-systems/chapter-2

Nói chung thì không có xiền hay tự hạn chế mình tiêu tiền mua sách xịn cũng là 1 cái khá hay (tất nhiên tớ có 500 credits để unlock lúc nào cần dùng để xem 1 đoạn nào đó rồi)

Về đọc miễn phí trên Manning

Và ngoài ra

Về trải nghiệm đọc trên Manning

Thực sự ban đầu tớ cũng chưa mò ra nút unlock 5 phút như ở trên đâu.

Cứ click vào đoạn văn nào là xổ ra unlock kiểu

Screenshot 2022-12-20 at 19-59-41 Chapter 2  User behavior and how to collect it · Practical Recommender Systems

Thực sự thì ban đầu cũng tiếc 500 tokens nên cứ nhìn figures và listings mà đọc.

Thế mà hóa ra cũng hay phết Quang à @@.

Tớ nhìn cái đống đấy thôi mà cũng hiểu sơ qua nội dung chương đấy.

Cũng hiểu họ muốn nói gì, đoạn code này làm gì (tất nhiên kiểu hiểu sơ sơ thôi chứ chi tiết thì chịu hix).

Về số người đọc trên Manning

Screenshot 2022-12-20 at 08-35-41 Chapter 2  User behavior and how to collect it · Practical Recommender Systems

Screenshot 2022-12-20 at 08-36-09 Chapter 2  User behavior and how to collect it · Practical Recommender Systems

Screenshot 2022-12-20 at 08-36-19 Chapter 2  User behavior and how to collect it · Practical Recommender Systems

Trong lúc mò mẫm cái trang web Manning tớ phát hiện ra 1 chức năng rất hay là xem có bao nhiêu người cùng đọc sách ở Manning với mình @@. Không phải cùng đọc quyển sách đấy không.

Nhìn vào hình trên thấy ở Việt Nam ở Hà Nội có nè, Sài Gòn có nè, Củ Chi có nè.

Cơ mà nhìn rộng ra thấy ở US đông người đọc thật =.=

Manning có quảng cáo 1/2 số sách về web development là họ viết. Công nhận dân Mỹ họ đọc ác thật =.=

Việt Nam mình có lẽ mải manufacturing hự hự 😞.

Về nội dung Chương 2

Okay thì quay lại chủ đề chính nội dung Chương 2 User Behavior and How to Collect It (Hành vi người sử dụng và làm sao để thu thập được hay là Làm sao để thu thập hành vi người sử dụng =.=)

Thực sự thì đọc kiểu free tớ đã thấy rất hay ở Table 2.1. Examples of evidence from Netflix (view table figure) rồi @@.

Hóa ra lúc design 1 website thì sau đấy bước nâng cao hơn là thu thập hành vi người dùng.

Có nghĩa là xem người dùng click cái gì, click đấy sẽ được đánh giá như thế nào =.=

Ở bảng Table 2.3. Page durations and a possible interpretation (view table figure) cũng khá hay khi phân tích theo thời gian người dùng đấy xem trang web. Càng xem nhiều chứng tỏ càng thích (very interested).

Rồi cả ở Figure 2.4. When an expansion link is clicked, it’s an indication of the visitor’s interest. This is an example from Amazon.co.uk. tớ cũng thấy bất ngờ khi họ nói nút Expand hay Read more để làm gì =.= Ấn vào đấy chứng tỏ người dùng có hứng thú với quyển sách đấy =.=

Thậm chí cả Figure 2.6. Netflix search result window, searching on wonder woman nói về phim mà Netflix không mua license nhưng có lẽ vẫn lưu lại Search Result để biết đâu nhiều người interest họ sẽ mua @@.

Cơ mà DisneyPlus có hết phim của Marvel rồi và quảng cáo cũng ác =.= Chắc ai mà mê mẩn Wonder Woman quá sẽ subscribe 1 tháng $9.99 bên đấy để xem thôi =.=

À nói đến Netflix có 1 cái rất hay Quang à là Netflix ở Việt Nam cho xem miễn phí 1 số bộ phim trên Android đấy (từ 2021/Nov)

https://about.netflix.com/en/news/netflix-launches-free-plan-in-vietnam

Không phải Ấn, Trung Quốc, Hàn hay Nhật có mà chỉ duy nhất Việt Nam có =.= Xịn xò thật. Không hiểu ở Việt Nam có cái gì hay mà Netflix lại muốn thu hút thế =.= Có lẽ do Millennias, Gen Z streaming nhiều quá @@@@@@.

Tớ cũng chưa thử xem là Netflix Free Plan trên Android có phim gì hự hự. Trên mạng cũng không thấy có cái list nào luôn =.=

Như bình thường sẽ có list Netflix ở Nhật có phim gì, Mỹ có phim gì chẳng hạn vì họ mua license của Hãng phim thành ra cũng phải tuân theo phim ý có ở nước ý hay không @@.

Hình Figure 2.7. Example of an outlier có lẽ nói về kiểu có user nào đó hành vi bất thường và có khi nên bỏ ra =.=

Hình Figure 2.8. When rating something on Amazon, it provides hints as to what the number of stars means. nói về rating trên Amazon từ 1 đến 5 sao cho 1 quyển sách =.=

Đọc đến đây tớ mới thấy bất ngờ Quang ạ.

Bảng Figure 2.13. Data model of an evidence logger cũng làm cho tớ hiểu hơn về MovieGEEKs web app. Có cái bảng này nhìn code sẽ dễ hơn hix. Cái này là design còn code là implementation T_T.

Listing 2.1. Creating an AJAX call to the collector: /moviegeek/static/js/collector.js

function add_impression(user_id, event_type, content_id,
                        session_id, csrf_token)
{
    $.ajax(                                                            1
           type: 'POST',                                               2
           url: '/collect/log/',
           data: {
                  "csrfmiddlewaretoken": csrf_token,                   3
                  "event_type": event_type,                            4
                  "user_id": user_id,                                  4
                  "content_id": content_id,                            4
                  "session_id": session_id                             5
                 },
           fail: function(){                                           6
                       console.log('log failed(' + event_type + ')')
                       }
            })
};

Đoạn code này viết theo kiểu JavaScript =.= Như tớ nói ở trên cũng hơi hiểu làm gì, modify cũng được có mà viết mới cũng chịu =.=

https://github.com/9health/moviegeek/blob/master/templates/moviegeek/index.html

Tớ cũng mò trong đoạn source code thì thấy dùng ở nhiều chỗ trong các file .html như ở trên cơ mà cũng chưa hiểu kỹ lắm file .html đấy =.= Thôi để phân tích chi tiết sau vậy.

Listing 2.2. Receiving calls from listing 2.1: /moviegeek/collector/view.py

@ensure_csrf_cookie
def log(request):

    if request.method == 'POST':                                  1
        date = request.GET.get('date', datetime.datetime.now())   2

        user_id = request.POST['user_id']
        content_id = request.POST['content_id']
        event = request.POST['event_type']
        session_id = request.POST['session_id']

        l = Log(
            created=date,
            user_id=user_id,
            content_id=str(content_id),
            event=event,
            session_id=str(session_id))
        l.save()                                                  3
    else:
        HttpResponse('log only works with POST')                  4

    return HttpResponse('ok')

Đoạn này thì hiểu là sau khi generate impression từ front-end thì sẽ lưu vào database O_O.

https://github.com/practical-recommender-systems/moviegeek/search?p=1&q=add_impression&type=Code

Event ở đây có thể là hover, là save_for_later, more_details, genre, buy.

Bảng Table 2.4. MovieGEEKs evidence points (view table figure) thì giúp hiểu rõ hơn là web app MovieGEEKs sẽ log gì.

Hình Figure 2.15. What happens when a user clicks a genre giúp hiểu cơ chế để log rõ hơn từ click, xử lý URL và lưu vào database.

Hình Figure 2.18. Generic data model nói về 2 bảng dữ liệu lưu user và hành vi của họ.

Hình Figure 2.19. User data model lưu nhiều thông tin user hơn hình trên!!!

Về nội dung Chương 2 sau khi unlock 5 phút

Thật sự đọc kỹ hơn phần chương 2 ví dụ về mua 1 cái máy xúc cây (chắc là cỡ hàng chục nghìn đô) thấy thiết kế 1 trang web đơn giản thôi cũng cần có sơ đồ UML kiểu hành vi thì mới có thể không bị sót được =.=

Người dùng vào, cảm nhận trang web, nhìn các nút 1 cách dễ dàng mới có thể tin và order được!!!

Ngoài ra thì cũng có 2 thể loại ứng xử (behaviors) là

Thực sự thì thông tin kiểu subjective kia thì cũng chưa chắc đúng hẳn vì nhỡ lúc ý người ý vui vui ấn nhầm 5-sao thì...

Có lẽ thông tin kiểu objective, lưu tự động kia nếu phân tích đúng sẽ đưa ra nhiều dữ liệu hay hơn @@.

VÌ có thể là người dùng nhìn thấy 1 poster nào hay hay, ở lại link đó 1 phút nhưng nhỡ có việc nào đó phải đi thì...

Nếu mình suggest cái đấy cho người dùng có vẻ sẽ hiệu quả hơn nhỉ T_T

Tóm lại 1 trang web cũng là 1 nơi mình thể hiện cảm xúc ý @@. Nó cũng giống như là khi nói chuyện giữa 2 người với nhau vậy sẽ có 1 cái mạch cảm xúc đấy đi kèm với mình =.=

Thật sự thì thiết kế 1 trang web kiểu chỉ cần nó đủ thông tin thôi có lẽ sẽ không quá phức tạp.

Đấy thì phân tích như thế mới thấy là người như tớ cũ thật, có lẽ là tớ cần nghe nhạc nhiều hơn, xem phim nhiều hơn để biết được cái bên trong mình (inner) như thế nào T_T. Hơặc là tớ cần dành thời gian tĩnh tâm suy nghĩ nhiều hơn @@.

Chưa biết cái nào hơn cả nhưng mà có lẽ chắc phải dành thời gian tiếp cận với bên ngoài thì mới mở mang đầu óc được @@. Chắc là 50/50 cho cả 2 hix hix.

Và có lẽ là tớ sẽ hợp với việc code cái collect này hơn là ngồi nghĩ là collect cái gì, design như thế nào, trông layout thế nào T_T.

Chắc là cái đấy phù hợp với Quang hơn hự hự. Tớ phù hợp cái đoạn AJAX với database thui... Có lẽ thế hix.

Về thời gian biểu của tớ hôm nay

Sáng nay thì 5 giờ chuông tớ đặt kêu rồi nhưng mà mẹ tớ đang ngủ say nên tớ cũng chưa dậy. Tớ cứ vừa nằm vừa suy nghĩ lơ mơ @_@.

Rồi 6h15 mẹ tớ dậy, tớ cũng bung mình dậy luôn rồi mở máy tính.

Tớ lúc ý cũng đắn đo lắm mình nên làm gì đây. Nên đọc Chương 9 tiếp đây hay là Chương 2 đây.

7h15 thì mẹ tớ gọi ra ăn sáng. Cơ mà mẹ tớ cứ làm gì ý, mãi tới 8h30 mới ăn sáng xong =.=

Vậy là tớ đã dùng 1 tiếng cho cái này rùi.

Còn 1 tiếng nữa tớ lại đắn đo xem là nên đọc tiếp code đoạn collector hay là ngồi update nốt file Ghi Nhận Cảm Xúc. Vì là 10h30 mẹ tớ bắt ăn trưa để 1h30 chiều có cuộc gặp chị kia rồi hix.

Vậy là tớ ngồi tới 9h30 để đọc nốt code trang kia vì nghĩ là đi gặp xong chắc trong đầu sẽ lại lộn xộn, sẽ lại suy nghĩ chả làm gì được tiếp hix.

9h30 đọc code xong thì tớ điền nốt file Future, Ghi Nhận Cảm Xúc và gửi nốt những files chưa gửi vào email chị ý mặc dù biết là đọc sẽ không kịp haizzzz.

Lời cuối cùng

Rất cảm ơn Quang đã giới thiệu cuốn sách này.

Tớ thấy cái này mà chuyển thành hardware code Verilog chắc là không thể luôn =.=

Ví dụ file spec tớ hay đọc là kiểu này này

https://www.csd.uoc.gr/~hy428/reading/i2c_spec.pdf

Đây là 1 chuẩn giao tiếp dùng thường hay có ở trong 1 con chip O_O. Có lẽ chip M1 cũng có, chip A15 trong iPhone cũng có...

Thường dân hardware bọn tớ khi có 1 file sẵn có rồi, có các bác ở trên rất giỏi đã nghỉ rồi, đã có 1 cái reference implementation và thực ra họ viết lại file đấy thôi hoặc là ghép nhiều proposal vào.

Quan trọng tại sao họ cần đưa ra file đấy cho các vendor khác đọc vì là nếu họ cứ giữ kín thì ai muốn đưa chuẩn I2C vào IC của họ rất khó.

I2C master là ở con chip còn I2C slave ở IC O_O.

I2C slave cũng có thể ở con chip được.

Master và slave cần có chứ không thì cũng không biết ai truyền nhận T_T. Kiểu thế.

Chuẩn này cũng không quá nhanh, thường họ dùng với tốc độ 1 Mbit thôi =.= Cơ mà có 1 cái là chuẩn này có từ lâu và nhiều người dùng rồi, nhiều công ty dùng rồi nên là họ cứ giữ mãi để backward compatibility. Còn chậm thì cũng không sao vì là chuẩn này thường dùng để config IC lúc ban đầu thôi và nếu có lấy data thì tốc độ 1M như thế là cũng đủ rùi ^_^

Tất nhiên có nhiều chuẩn khủng khiếp hơn gọi là High Speed lên tới cả 100 Mbps, 1 Gbps hay như card đồ hoạ là 32 Gbps hay là giao tiếp 2 con chip M1 Max thành 1 con chip M1 Ultra trong MacStudio ý lên tới 2 Tbps =.= Khủng khiếp thật.

Thôi cảm ơn Quang rất nhiều đã đọc đến đây và giới thiệu tớ quyển sách.

Tối nay nhà tớ ăn cơm muộn, lúc 8h30 hix rồi xem trao giải VinFuture tới 10h đêm.

Giờ là 11h15 thì cũng đang xem nốt phim "HÀNH TRÌNH CÔNG LÝ" đang rất là phức tạp và căng thẳng hix T_T.

Sorry Quang nữa vì đã gửi muộn hix.

Bài viết này có 16.3K ký tự, 3.1K ký tự và đọc trong vòng 15 phút!!!

quangvv9Life commented 1 year ago

Hi Hải,

Thank Hải đã đọc và phản hồi lại về C2 của PRS nhé. Tớ đọc cũng trong giai đoạn 6 tháng trước khi Hải vẫn còn ở bên BkonTech nên là cũng nhớ nhớ quên quên. Mà đặc biệt là liên quan đến code nữa mà dở kindle ra đọc nên là hơi khó, mặc dù logic và các ý chính về kiến trúc linh tinh các thứ thì cũng có nhớ mang máng

Đọc như vậy để hiểu qua về RS và vận dụng vào cái app 9Health thôi. 9Health ban đầu cũng sẽ không đến mức phức tạp như cái web movieGeek này là phải thu thập lại hết hành vi người dùng thông qua lia chuột, chạm hay click đâu.

Tất cả các thao tác đó tớ đang hình dung là thông qua việc track : food & activities của họ (nếu có thể thu được touch thì sẽ sử dụng cho các use-case khác sau này nâng cao hơn) Dựa vào tracking đó thì hệ thống sẽ chạy để so sánh thực tế và mục tiêu đang còn là bao nhiêu và lấy ra các món ăn để giúp họ đạt được mục tiêu trong các hoạt động tiếp theo (bữa ăn tiếp theo, buổi tập luyện tiếp theo, etc.)

Có 1 vấn đề đó là sau mỗi 1 tuần nên có 1 cái gì đó nó "chạy được" vậy Hải thử nghĩ xem đọc xong chương 9 thì có thể áp dụng được gì cho phần database của food hiện tại không ?

Về các task của tuần này thì tớ vẫn đang ghi lại và theo dõi bằng taiga sau buổi họp t7 hàng tuần :

Phần của Hải : trong này có 1 task tớ đang dự định sẽ dành thời gian đọc lại chương 7 (sau khi xong phần màn hình tính năng chính)để trao đổi thêm với Hải cho nhanh. image

Phần của anh Công : image

Phần của tớ : image

Thank Hải đã dành thời gian để đọc cuốn PRS nhé !!! Hy vọng là sẽ áp dụng được để xây dựng back-end đằng sau cho 9Health và các app khác về sau này !!!

Cố gắng 1 tháng nữa sẽ có sản phẩm 9Health đầu tiên - 1st MVP ra lò nhé !!!

Đợt này tớ nghỉ bên MB rồi nên là nếu cần gặp offline thì tớ vs Hải có thể hẹn trước vào khoảng thời gian nào tiện cho Hải nhé !!!

Cám ơn Hải 1 lần nữa !!!

BR Quang

9health commented 1 year ago

Hello @quangvv9Life,

Về Microsoft 365 bị deactivated/locked

Cảm ơn Quang đã tích cực liên hệ với Microsoft và cùng họ fix lỗi nhé @@.

May quá Quang kịp thời đáp ứng chứ tớ thì chắc lắc lư tới vài tuần mất...

Có lẽ do ở Việt Nam có 1 số bạn đăng ký mấy chương trình Microsoft 365 Developer Program mà không dùng @@.

https://developer.microsoft.com/microsoft-365/dev-program

Chương trình này cứ 3 tháng nếu mà không có output gì thì sẽ bị dừng.

Benefits thì có lẽ được Office, Outlook, 1 TB OneDrive, Teams như của mình.

Output họ đòi là phải viết mấy cái Power Apps cho họ hay 1 cái gì đó liên quan tới Power Platform chẳng hạn...

Họ sẽ dùng AI để tracking mấy cái đấy T_T.

Cũng là 1 cách hay để vừa tăng khả năng lập trình, vừa dùng được Microsoft 365 miễn phí ^_^

Cơ mà quan trọng là cần phải làm cái gì hix thì tớ chịu không nghĩ ra =.=

Về Chương 2 tớ thực hành hôm nay

Hôm nay thì tớ đặt đồng hồ dậy lúc 5h sáng cơ mà mẹ đang ngủ nên 6 giờ mới dậy =.=

Tớ cũng khá là mệt vì tối qua không ngủ được =.= Chả hiểu do nói chuyện chiều hôm qua hay là do uống cafe đen đá lúc 2h chiều nữa haizzz. Hình như 1 hay 2 giờ sáng mới ngủ kiểu hơi thao thức =.= Cứ suy nghĩ, suy nghĩ mãi @@@@@@@@@@.

Sáng nay lúc mở máy tính ra cũng rất là đắn đo.

Làm theo cái thứ 3 mà ngồi mò mẫm AJAX thì lâu quá, chắc học mất thêm 1 tuần mất =.=

Mà đọc tiếp Chương 2 kiểu miễn phí 5 phút thì tớ thấy cũng hơi chán vì như bài viết hôm qua Quang thấy thì tớ cũng đá nắm qua cài sườn Chương 2 rồi. Đọc kỹ hơn cũng chỉ biết thêm hơn thôi @@.

Thôi thì tớ quyết định chuyển sang hướng code và cũng thấy hay phết.

Output của tớ đặt ra trong 2 tiếng (thực ra có 1 tiếng 30 phút thôi vì 7h30 mẹ tớ gọi ăn sáng rồi =.=) là hiểu được lúc mình lia con chuột vào cái poster hay là mình ấn vào 1 bộ phim thì ở dưới sẽ xảy ra những sự kiện gì @@.

Vậy là đầu tiên tớ mò mẫm vào database SQLite3 của MovieGEEKs. Files .sqlite3 khá là nặng hơn 50MB.

Về MovieGEEKs database

Đây là các tables có trong database


sqlite> .headers on
sqlite> .mode column

sqlite> .tables
analytics_cluster           django_migrations         
analytics_rating            django_session            
auth_group                  lda_similarity            
auth_group_permissions      movie_description         
auth_permission             movie_genre               
auth_user                   moviegeeks_genre          
auth_user_groups            moviegeeks_movie          
auth_user_user_permissions  recs                      
collector_log               seeded_recs               
django_admin_log            similarity                
django_content_type       

Quang nhìn có thể thấy phần liên quan tới users' behavior sẽ nằm trong table collector_log.

Tớ dùng lệnh SQL xem và thấy cũng đúng thật 🤔.


sqlite> SELECT * FROM collector_log WHERE id > 80; 

id          created                     content_id  event       session_id                            user_id    
----------  --------------------------  ----------  ----------  ------------------------------------  -----------
81          2022-12-19 04:47:56.503467  2076298     details     133225e2-7f58-11ed-a073-000d3a5a3fa5  68256497607
82          2022-12-19 04:48:04.656853  0           genre:Film  133225e2-7f58-11ed-a073-000d3a5a3fa5  68256497607
83          2022-12-19 04:48:07.996798  0           genre:Hist  133225e2-7f58-11ed-a073-000d3a5a3fa5  68256497607
84          2022-12-19 04:57:11.047484  499097      details     8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
85          2022-12-19 04:57:12.306327  499097      more_detai  8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
86          2022-12-19 04:57:57.244660  0           genre:Come  8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
87          2022-12-19 04:58:05.182187  870154      details     8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
88          2022-12-19 04:58:05.356919  870154      details     8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
89          2022-12-19 04:58:06.607024  1361336     details     8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
90          2022-12-19 04:58:07.785532  1361336     more_detai  8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
91          2022-12-19 04:58:07.791106  1361336     details     8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939

Tiếp đó tớ mò mẫm xme thằng moviegeeks_movie là gì.

sqlite> SELECT * FROM moviegeeks_movie LIMIT 10;

movie_id    title                                    year      
----------  ---------------------------------------  ----------
0000008     Edison Kinetoscopic Record of a Sneeze   1894      
0000010     La sortie des usines Lumière             1895      
0000012     The Arrival of a Train                   1896      
25          The Oxford and Cambridge University Boa  1895      
0000091     Le manoir du diable                      1896      
0000131     Une nuit terrible                        1896      
0000417     A Trip to the Moon                       1902      
0000439     The Great Train Robbery                  1903      
0443        Hiawatha, the Messiah of the Ojibway     1903      
0000628     The Adventures of Dollie                 1908      

====================================================

Trong đống database đấy có rất nhiều phim luôn =.= Nó xổ ra 1 đống nếu tớ không LIMIT

Vậy là tớ đếm thử xem có bao nhiêu rows ở trong table đấy

sqlite> SELECT COUNT (*) FROM moviegeeks_movie;

COUNT (*) 
----------
38018     

sqlite> PRAGMA table_info(moviegeeks_movie);

cid         name        type         notnull     dflt_value  pk        
----------  ----------  -----------  ----------  ----------  ----------
0           movie_id    varchar(16)  1                       1         
1           title       varchar(512  1                       0         
2           year        integer      0                       0   

Chà 38K nhiều thật.

Xem thử bảng movie_genre có gì.

sqlite> SELECT COUNT(*) FROM movie_genre;

COUNT(*)  
----------
90081     

sqlite> PRAGMA table_info(movie_genre);

cid         name        type        notnull     dflt_value  pk        
----------  ----------  ----------  ----------  ----------  ----------
0           id          integer     1                       1         
1           movie_id    varchar(16  1                       0         
2           genre_id    integer     1                       0         

sqlite> SELECT * FROM movie_genre WHERE id < 10;

id          movie_id    genre_id  
----------  ----------  ----------
1           0000008     1         
2           0000008     2         
3           0000010     1         
4           0000010     2         
5           0000012     1         
6           0000012     2         
7           0000091     2         
8           0000091     3         
9           0000131     2         

Cũng kha khá nhiều, tận 90K rows. Bảng này giống như 1 bảng mapping (ánh xạ) vậy.

Còn đây là bảng movie_description


sqlite> PRAGMA table_info(movie_description);

cid         name        type        notnull     dflt_value  pk        
----------  ----------  ----------  ----------  ----------  ----------
0           id          integer     1                       1         
1           movie_id    varchar(16  1                       0         
2           imdb_id     varchar(16  1                       0         
3           title       varchar(51  1                       0         
4           descriptio  varchar(10  1                       0         
5           genres      varchar(51  1                       0         
6           lda_vector  varchar(56  0                       0         
7           sim_list    varchar(51  1                       0         

sqlite> SELECT * FROM movie_description LIMIT 10;

Bảng này có lẽ không dùng thì phải... Tớ không thấy gì trong này.

Đây là bảng movie_genre

sqlite> SELECT * FROM moviegeeks_genre;

id          name       
----------  -----------
1           Documentary
2           Short      
3           Horror     
4           Comedy     
5           Action     
6           Adventure  
7           Fantasy    
8           Sci-Fi     
9           Crime      
10          Western    
11          Drama      
12          Romance    
13          History    
14          Family     
15          War        
16          Sport      
17          Biography  
18          Mystery    
19          Thriller   
20          Animation  
21          Music      
22          Musical    
23          Film-Noir  
24          Adult      
25          Talk-Show  
26          News       
27          Reality-TV 
28          Game-Show  

Bảng này django_session dùng cho Django

sqlite> SELECT * FROM django_session;

session_key                       session_data                                                                                                                                                  expire_date               
--------------------------------  --------------------------------------------------------------------------------------------------------------------                                          --------------------------
icprrbmtatjbc3a032te6lg1e50zpml7  Yzc2NGY5OWU2YmY1ZTFhOWU0NjY0Mzk5NjExZDExY2NlMDZmNGVjYzp7InNlc3Npb25faWQiOiJhYzYzMWYwNC03YmEzLTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjoxNDI3MTA1NzMzOX0=  2022-12-28 11:37:22.092106
fb83i3arftl9174usgjchll5wfl9zo3q  Njg4ZDBiM2M0MWY5M2ZiOWI1YmU4MGY4YjU5NmU5Y2M3YzQ3YTllZjp7InNlc3Npb25faWQiOiI3NzQyZjBkMi03YmE0LTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo3ODExNTk1MzI4NH0=  2022-12-28 11:43:02.430835
f1igkjh1uj8p95werooyye2lirxo98kh  MDJmMDU1MDg0ODQ1MjE3ZDg3Y2RjNWFlNzVmOTkzMWM2ZmI2ZDI1Njp7InNlc3Npb25faWQiOiJkMGM3MjQzNC03YmE0LTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjoxODkzMTY5OTQ2M30=  2022-12-28 11:45:32.614660
t1v0n5hddklmhlkk9yttlb6cnz21yzxb  YTM0MzBhNGJlNmU0NjJjYzE0Yjc4Njc3ODllOWM3MDhiYTczMGNiYzp7InNlc3Npb25faWQiOiJlMzYzMmQ0MC03YmE0LTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo4MTQ5OTY1MTEyNH0=  2022-12-28 11:46:03.838964
ixjcqlcbcf971mf9frf9u4q3166lg54k  YmM0YjQxOGEzY2RjZDhjZGJhYTQxM2M0ZTRiOWIwZDAyOTExZmQ2Yzp7InNlc3Npb25faWQiOiI4NzUyNGY1MC03YmE4LTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjozMzYwNjE5OTY0NX0=  2022-12-28 12:12:07.364549
dkobynksza4y1chbbsqcuziinp7v4ioo  ZWRkMWRiNDQxMzhlNWY5MjUyYzA4ZGQ4ZmY2NWQzN2NhOTU2YWE3Yjp7InNlc3Npb25faWQiOiI1YzhhYTUxNC03YmE5LTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo1MjAzMTgxMTY5MX0=  2022-12-28 12:18:05.086861
5es2xin58qehr6kf3xp7hiajphl3t1la  ODc4OWNmMDY5MzVhNjEwNDVmMjZhNGMzNmZmNzQ0OTYxNTEzZjA1NDp7InNlc3Npb25faWQiOiIwYjA2MDBkNC03YmFhLTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo3MjE2MzgzODE3Nn0=  2022-12-28 12:22:57.819620
rhuygpe1ajgxolq02s7gbnd53l133gzf  NmNlYmEzNDA0MTUxODhhNzZkNjEyOGE0YTRkZjQ2YTEwNGYyNDJhMTp7InNlc3Npb25faWQiOiIwYzE0ZTI2YS03YmFhLTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo3OTAyMjg0OTAwOH0=  2022-12-28 12:22:59.596358
ext5c9zeic6k5c88h5njtqowwajljr4a  YTgyMDhiOGVlNzc1Y2VmOGEzNDFmNDkxMTg0MzBiMDlmMWZhYWFkNjp7InNlc3Npb25faWQiOiI0NjE1Y2NmZS03YmFhLTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo2Nzg5MDU4NDc4OH0=  2022-12-28 12:24:36.911950
x8tdcxcev7a1upm78m9w7vk3uwd330sk  MzZmNjU2OGJmZmIzOWViMTc2M2I5YTYzOTU5NWQ3NGFjNzY4ODFhNzp7InNlc3Npb25faWQiOiJmYmU3MDE4Ni03YmFjLTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjo1NjczMTEzMjUyNX0=  2022-12-28 12:44:00.939838
uirohdmbg61j6umoqtlcs8pwkq2kqocz  MmE2OWZkZDUzODVhNzBkOWQ2NjM4MjUwZDEyMjE5ZDUzZjBlMTE3NDp7InNlc3Npb25faWQiOiJlYjljMjkxYS03YmIwLTExZWQtYWZkMi0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjoyNDIzMjgzODQ0MH0=  2022-12-28 13:12:11.593076
eqj4js8b52nzia4a86eengpf0jtv20g4  ZTllYTc3NzdjOGM1MmFiMjhhMjk1Y2I1YjUwZDZiMDA0ZDI0ZjFmMTp7InNlc3Npb25faWQiOiI0MTczOWJmNi03YzIwLTExZWQtOTZjNy0wMDBkM2E1YTNmYTUiLCJ1c2VyX2lkIjozOTQzMzY4MjEwMn0=  2022-12-29 02:29:09.861116

Về hoạt động thu thập hành vi người dùng (collect users' behavior)

Vậy là tớ hiểu sơ sơ về MovieGEEKs web app database rồi.

Tớ sẽ tìm hiểu xem khi mình lia chuột vào 1 cái poster phim thì chuyện gì sẽ xảy ra.

Khi lia chuột vào 1 poster thì sẽ có 1 lệnh POST này gửi về server ở back-end từ front-bend

POST
    http://ninehealth.westus.cloudapp.azure.com:8080/collect/log/

{
    "csrfmiddlewaretoken": "p2dqYFdaQyqbzylKyWCQJKeCBJW32N7909FwxTABgwQf2NJ7OxpiOqWLECNcl1zA",
    "event_type": "details",
    "user_id": "68159542309",
    "content_id": "10016180",
    "session_id": "6079aab2-80bd-11ed-916f-000d3a5a3fa5"
}

Tớ dùng Firefox để debug cho dễ vì Safari ẩn đi hết rùi @@.

Và cũng không hiểu sao trang web đấy vào Safari cứ chậm chậm hay không vào được sao đó. Chắc do không có https =.=

Ở phần Python log sẽ xuất hiện những log sau

(venv_3.6.9) ninehealth@LinuxVM15:~/work/moviegeek$ python3 manage.py runserver 0.0.0.0:8080
Watching for file changes with StatReloader
Performing system checks...

/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/requests/__init__.py:91: RequestsDependencyWarning: urllib3 (1.26.5) or chardet (3.0.4) doesn't match a supported version!
  RequestsDependencyWarning)
System check identified no issues (0 silenced).
December 20, 2022 - 23:23:34
Django version 2.2.27, using settings 'prs_project.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.
ensured id:  68159542309

[20/Dec/2022 23:23:57] "GET / HTTP/1.1" 200 24513
[20/Dec/2022 23:23:57] "GET /static/js/collector.js HTTP/1.1" 200 618
[20/Dec/2022 23:23:59] "GET /rec/chart HTTP/1.1" 301 0
recs from association rules:
[]
[20/Dec/2022 23:23:59] "GET /rec/ar/68159542309/ HTTP/1.1" 200 12
[20/Dec/2022 23:23:59] "GET /rec/chart/ HTTP/1.1" 200 215
cf sorted_items is: {}
[20/Dec/2022 23:23:59] "GET /rec/cb/user/68159542309/ HTTP/1.1" 200 38
[20/Dec/2022 23:23:59] "GET /rec/cf/user/68159542309/ HTTP/1.1" 200 38
Not Found: /favicon.ico
[20/Dec/2022 23:24:00] "GET /favicon.ico HTTP/1.1" 404 2554
Not Found: /tmUnblock.cgi
[20/Dec/2022 23:36:03] "POST /tmUnblock.cgi HTTP/1.1" 404 2530
Not Found: /google.com:443
[20/Dec/2022 23:58:21] "CONNECT google.com:443 HTTP/1.1" 404 1654
ensured id:  28078995799
[21/Dec/2022 00:05:58] "GET / HTTP/1.1" 200 24513
[21/Dec/2022 00:10:25] "POST /collect/log/ HTTP/1.1" 200 2
sqlite> SELECT * FROM collector_log WHERE id > 90 LIMIT 10;

id          created                     content_id  event       session_id                            user_id    
----------  --------------------------  ----------  ----------  ------------------------------------  -----------
91          2022-12-19 04:58:07.791106  1361336     details     8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
92          2022-12-21 00:10:25.121021  10062556    details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309

sqlite> SELECT * FROM moviegeeks_movie WHERE movie_id = 10062556;

movie_id    title                      year      
----------  -------------------------  ----------
10062556    Bhuj: The Pride of India   2021      

Tớ cũng thử các action khác

[21/Dec/2022 00:29:00] "GET /movies/movie/2382320/ HTTP/1.1" 200 19538
[21/Dec/2022 00:29:01] "GET /rec/association_rule/2382320/ HTTP/1.1" 200 12
[21/Dec/2022 00:29:01] "GET /rec/cb/item/2382320/ HTTP/1.1" 200 36
Not Found: /tmUnblock.cgi
[21/Dec/2022 00:29:13] "POST /tmUnblock.cgi HTTP/1.1" 404 2530

sqlite> SELECT * FROM collector_log ORDER BY id DESC LIMIT 8;

id          created                     content_id  event         session_id                            user_id    
----------  --------------------------  ----------  ------------  ------------------------------------  -----------
96          2022-12-21 00:26:18.862728  2382320     more_details  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
95          2022-12-21 00:26:12.800817  2382320     details       6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
94          2022-12-21 00:16:29.620849  0           genre:Action  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
93          2022-12-21 00:14:49.493932  10016180    details       6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
92          2022-12-21 00:10:25.121021  10062556    details       6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
91          2022-12-19 04:58:07.791106  1361336     details       8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
90          2022-12-19 04:58:07.785532  1361336     more_details  8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939
89          2022-12-19 04:58:06.607024  1361336     details       8c8cf902-7f59-11ed-a073-000d3a5a3fa5  73165680939

Ở phần database tớ check thì đã xuất hiện bản ghi mới, giống với bộ phim tớ lia chuột vào.

[21/Dec/2022 00:32:46] "POST /collect/log/ HTTP/1.1" 200 2

sqlite> SELECT * FROM collector_log ORDER BY id DESC LIMIT 8;

id          created                     content_id  event       session_id                            user_id    
----------  --------------------------  ----------  ----------  ------------------------------------  -----------
101         2022-12-21 00:32:46.135319  3480822     buy         6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
100         2022-12-21 00:30:46.902331  3480822     details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
99          2022-12-21 00:30:46.898870  3480822     more_detai  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
98          2022-12-21 00:30:18.044994  3480822     details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309

Đây là 1 số log Quang có thể thấy...

Log khi search

[<Movie: Avengers: Age of Ultron >, <Movie: Avengers: Infinity War >, <Movie: Avengers: Endgame >, <Movie: Avengers Grimm >, <Movie: Avengers: Age of Ultron Parody >]
[21/Dec/2022 00:33:38] "GET /movies/search/?q=avengers HTTP/1.1" 200 17661
[21/Dec/2022 00:33:38] "GET /rec/chart/ HTTP/1.1" 200 265

Nhiều log hơn khi search

[21/Dec/2022 00:32:46] "POST /collect/log/ HTTP/1.1" 200 2
[<Movie: Avengers: Age of Ultron >, <Movie: Avengers: Infinity War >, <Movie: Avengers: Endgame >, <Movie: Avengers Grimm >, <Movie: Avengers: Age of Ultron Parody >]
[21/Dec/2022 00:33:38] "GET /movies/search/?q=avengers HTTP/1.1" 200 17661
[21/Dec/2022 00:33:38] "GET /rec/chart/ HTTP/1.1" 200 265
[21/Dec/2022 00:34:37] "GET /movies/movie/4154756 HTTP/1.1" 301 0
ensured id:  68159542309
[21/Dec/2022 00:34:38] "GET /movies/movie/4154756/ HTTP/1.1" 200 19536
[21/Dec/2022 00:34:38] "GET /rec/association_rule/4154756/ HTTP/1.1" 200 12
[21/Dec/2022 00:34:38] "GET /rec/cb/item/4154756/ HTTP/1.1" 200 36

{
    "GET": {
        "scheme": "https",
        "host": "api.themoviedb.org",
        "filename": "/3/find/tt4154756",
        "query": {
            "external_source": "imdb_id",
            "api_key": "[Tớ tạm che cái này chứ debug trong Web Developer của Firefox là thấy =.=]"
        }
    }
}

{
    "movie_results": [
        {
            "adult": false,
            "backdrop_path": "/mDfJG3LC3Dqb67AZ52x3Z0jU0uB.jpg",
            "id": 299536,
            "title": "Avengers: Infinity War",
            "original_language": "en",
            "original_title": "Avengers: Infinity War",
            "overview": "As the Avengers and their allies have continued to protect the world from threats too large for any one hero to handle, a new danger has emerged from the cosmic shadows: Thanos. A despot of intergalactic infamy, his goal is to collect all six Infinity Stones, artifacts of unimaginable power, and use them to inflict his twisted will on all of reality. Everything the Avengers have fought for has led up to this moment - the fate of Earth and existence itself has never been more uncertain.",
            "poster_path": "/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
            "media_type": "movie",
            "genre_ids": [
                12,
                28,
                878
            ],
            "popularity": 182.007,
            "release_date": "2018-04-25",
            "video": false,
            "vote_average": 8.266,
            "vote_count": 25907
        }
    ],
    "person_results": [],
    "tv_results": [],
    "tv_episode_results": [],
    "tv_season_results": []
}

Đây là error xuất hiện khi tớ ấn vào link user để xem User Profile ở góc trên cùng bên phải.


  File "/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ninehealth/work/moviegeek/recommender/views.py", line 192, in recs_bpr
    sorted_items = BPRRecs().recommend_items(user_id, num)
  File "/home/ninehealth/work/moviegeek/recs/bpr_recommender.py", line 44, in recommend_items
    self.load_model(self.save_path)
  File "/home/ninehealth/work/moviegeek/recs/bpr_recommender.py", line 20, in load_model
    with open(save_path + 'item_bias.data', 'rb') as ub_file:
FileNotFoundError: [Errno 2] No such file or directory: './models/bpr/item_bias.data'

[21/Dec/2022 00:36:57] "GET /rec/fwls/user/68159542309/ HTTP/1.1" 200 38
[21/Dec/2022 00:36:57] "GET /rec/bpr/user/68159542309/ HTTP/1.1" 500 17115
Internal Server Error: /rec/funk/user/68159542309/
Traceback (most recent call last):
  File "/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/ninehealth/work/moviegeek/venv_3.6.9/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/ninehealth/work/moviegeek/recommender/views.py", line 183, in recs_funksvd
    sorted_items = FunkSVDRecs().recommend_items(user_id, num)
  File "/home/ninehealth/work/moviegeek/recs/funksvd_recommender.py", line 53, in recommend_items
    self.load_model(self.save_path)
  File "/home/ninehealth/work/moviegeek/recs/funksvd_recommender.py", line 23, in load_model
    with open(save_path + 'user_bias.data', 'rb') as ub_file:
FileNotFoundError: [Errno 2] No such file or directory: './models/funkSVD/2018-01-01 10:01:34.179393/model/user_bias.data'

[21/Dec/2022 00:36:57] "GET /rec/funk/user/68159542309/ HTTP/1.1" 500 17209
[21/Dec/2022 00:36:57] "GET /rec/sim/user/68159542309/pearson/?min=4 HTTP/1.1" 200 98
[21/Dec/2022 00:36:57] "GET /rec/sim/user/68159542309/jaccard/?min=4 HTTP/1.1" 200 98

Tớ sẽ reference ở issue check log.

Đây là thông tin hiện lên trang web và thông tin dưới database về user.

sqlite> SELECT * FROM collector_log ORDER BY id DESC LIMIT 18;
id          created                     content_id  event       session_id                            user_id    
----------  --------------------------  ----------  ----------  ------------------------------------  -----------
101         2022-12-21 00:32:46.135319  3480822     buy         6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
100         2022-12-21 00:30:46.902331  3480822     details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
99          2022-12-21 00:30:46.898870  3480822     more_detai  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
98          2022-12-21 00:30:18.044994  3480822     details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
97          2022-12-21 00:30:01.251167  0           genre:Adve  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
96          2022-12-21 00:26:18.862728  2382320     more_detai  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
95          2022-12-21 00:26:12.800817  2382320     details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
94          2022-12-21 00:16:29.620849  0           genre:Acti  6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
93          2022-12-21 00:14:49.493932  10016180    details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309
92          2022-12-21 00:10:25.121021  10062556    details     6079aab2-80bd-11ed-916f-000d3a5a3fa5  68159542309

Recent Log
3480822 | buy | Dec. 21, 2022, 12:32 a.m.
3480822 | details | Dec. 21, 2022, 12:30 a.m.
3480822 | more_details | Dec. 21, 2022, 12:30 a.m.
3480822 | details | Dec. 21, 2022, 12:30 a.m.
0 | genre:Adventure | Dec. 21, 2022, 12:30 a.m.
2382320 | more_details | Dec. 21, 2022, 12:26 a.m.
2382320 | details | Dec. 21, 2022, 12:26 a.m.
0 | genre:Action | Dec. 21, 2022, 12:16 a.m.
10016180 | details | Dec. 21, 2022, 12:14 a.m.
10062556 | details | Dec. 21, 2022, 12:10 a.m. 

Tớ cũng thấy 2 bên giống nhau nhưng trên web hiển thị xấu quá =.=

Về bug hoặc là feature tớ phát hiện ra

Tớ cũng không rõ đây là bug hay feature của tác giả nữa vì cũng chưa đọc kỹ Chương 2 @@.

Cơ mà tớ nghĩ đấy là bug.

Số là khi tớ kiểm tra tính năng Search và ra 1 vài phim, tớ lia chuột vào và hiện thêm thông tin về phim nhưng mà không có lệnh POST nào được gửi xuống.

Trong khi ở Home page hay trong 1 Genre nào đó trên MovieGEEKs web app khi làm như tớ sẽ có lệnh POST gửi thông tin đấy về để recommend...

Như tớ đánh giá đây là bug.

Nếu mà cần fix thì chọc ngoáy vào phần front-end modify cũng khá là hay ho @_@.

Tớ cũng biết cách check kết quả thế nào rùi 🤔.

Một số vấn đề khác

Về múi thời gian trên server

Tớ cũng không nhớ lắm nhưng mà có lần đọc trên StackOverflow họ bảo Date Time trên OS chạy database nên để kiểu GMT +0

Cơ mà hôm trước tớ ngứa tay để về GMT +7 là giờ Việt Nam @@.

Hình như làm cho database không collect được thông tin nữa hix.

Cơ mà restart lại hết và bật lại web app thì lại chạy bình thường như ở trên hix. Log ngày 2022-12-21 đó.

Nhưng mà tớ cũng cần check lại hix

Về Google Collab

Tớ xem qua log lỗi thiếu file ở trên thì hình như mình cần phải training gì đó thì phải @@.

Qua tớ mới nhớ ra Google Collab Jupyter Notebook training có 16GB RAM thì phải, 4-core hay 16-core CPU nữa =.= Train nhanh lắm.

Tớ có dùng để tách các nhạc và voice riêng ra cơ mà cũng không được hoàn hảo lắm =.=

https://github.com/deezer/spleeter

Want to try it out but don't want to install anything ? We have set up a Google Colab.

Quang có thể thử ở link trên @@, rất tiện luôn. Có người mò tăng lên 24 GB RAM @@.

https://towardsdatascience.com/upgrade-your-memory-on-google-colab-for-free-1b8b18e8791d

Tất cả những cái này của Google đều là free hết @@. Có thể chạy lệnh Linux trong Jupyter Notebook đấy luôn @@. Xịn thật. Bravo Google 👋.

Các lệnh SQLite cơ bản

Cái này có lẽ tớ sẽ tạo 1 trang Wiki riêng...

Về cảm nhận của tớ khi ngồi mò mẫm check database, Python log, POST request

Thật sự thì tớ đúng là không có khả năng design thật vì đầu tớ có lẽ có nhiều constrain quá @@.

Thôi thì không design được chuyển qua check/test/verify cũng có cái hay @@.

Hi vọng tớ sẽ hiểu cái lỗi trên và fix được.

Nay thì tớ cũng chưa dùng hết 5-phút đọc sách miễn phí @@. Cố dùng nào @@.

Về họp với Microsoft chiều nay

Thanks Quang đã gửi tớ invitation cơ mà tớ nghĩ lại có cái gì đó sai sai.

Họ gửi mỗi cho Quang trong khi không gửi cho tớ với anh Công.

Nếu mà tớ join cũng hơi kỳ vì trong mailing list của họ không có tớ @@.

Tớ định đến nhà Quang ăn trưa rồi ngồi chiều nói chuyện 1 tí rồi 16h30 họp có okay không @@.

Mẹ tớ hôm nay đi hát 11h30 mới về. Mẹ tớ còn có ý định về quê Hà Tây mà không biết là 13h, 15h hay 17h về nữa =.=

Tớ định đi luôn cho lành @@@@.

Quang ăn rồi thì để dành tớ ít cơm @@.

Nếu mà Quang ngại ở nhà Quang có thể ra chỗ cafe nào gần đó họp cũng được @@.

Tớ sẽ đi xe 142 ra gần nhà Quang @@.

Tạm thời tớ sẽ đặt Airplane mode điện thoại trong khoảng 1h30 phút nhé @@. Hơi tiêu cực chút. Mong Quang thông cảm hix...

Next task có lẽ tớ sẽ đọc Chương 3 cho dễ chứ Chương 7 hay 9 nhìn khó lắm... Sorry Quang...

À về bài post của Quang ở trên tớ có đọc qua rồi nhưng mà chưa biết comment lại thế nào @@. Thanks Quang đã copy ảnh từ Taiga, tạo task nữa nhé @@@@@.

Tớ sẽ nhắn lại sau nhé!!! Thanks Quang!!!

Tớ còn chưa viết note ngồi nói chuyện hôm qua với chị kia nữa haizzz.

9health commented 1 year ago

Hello @quangvv9Life,

Thanks Quang đã nhắn tin cho tớ ở qua iMessage nhé @@.

Tớ cũng đọc mấy cái Quang gửi tối qua thôi hix. Cảm ơn Quang vẫn tiếp tục làm hix. Bao nhiêu lời mời gọi ở ngoài kia T__T. Giá mà có ai replace được thì tốt nhỉ...

Hôm trước nữa thì buổi đêm về muộn, định ngồi viết cái note mà chắc do đêm trước nữa không ngủ nên là thôi đi ngủ chứ viết chắc đến 3-4 giờ sáng mất =.=

11h30 tối T4 đi ngủ. 6h sáng T5 dậy và cũng đắn đo Chương 2 tiếp tục hay là Chương 3

Về Chương 3

Chương 2 có vẻ sau khi tớ nói chuyện với Quang cũng hòm hòm hiểu rồi =.=

Xem code, check log từ front-end tới back-end cùng Quang luôn chiều T4 rồi.

Công nhận ngồi nói lại tớ mới phát hiện ra phần Search front-end có 1 đoạn code chạy để log vào database mà lại không chạy như tớ với Quang thử.

Chắc bug thật rồi.

Tớ sẽ log lại ở 1 cái issue khác.

Thế là tớ quyết chuyển sang Chương 3 đọc thôi.

Lần này tớ cũng đọc theo kiểu nhìn hình trước, nhìn cái gì chưa bị lock và đoán nội dung.

Cũng hiểu Chương 3 là nói về phần theo dõi (monitor) các thông tin và hiển thị ra.

Trong này có 1 cái hình rất hay chắc là dành cho dân marketing với design

Figure 3.5. A conversion funnel based on logging in at Amazon.

Từ hình này có thể biết được action nào tương ứng với cảm nhận của user như thế nào.

Nếu mà ấn nút Buy là thành công nhất rồi. Còn nếu mà chưa ấn, chỉ xem details thôi cũng là thành công một phần @@.

Hình này giống như là 1 cái phễu vậy. Càng xuống phía dưới thì tỷ lệ càng thấp đi, quy luật rồi @@.

Nếu mà mình log lại, vẽ hình lại mà không ra như thế chứng tỏ có 1 cái vấn đề gì đó.

Hoặc ông nào vào mà cứ buy liên tục chắc cũng có vấn đề gì đó, không phải người bình thường =.=

Thuật ngữ Conversion Rate trong này có thể dịch nôm ra là tỷ lệ quy thuật :|.

Nó giống như là convert 1 người từ Đạo này sang Đạo kia vậy @@.

Trong nầy họ cũng đưa 1 đoạn SQL code để giải thích tính tỷ lệ đấy thế nào

Listing 3.1. SQL script to calculate conversion rate

select count(distinct(session_id)) as visits,
       count(case when conversion > 0
                  then 1 end) as conversions     1
from
( select session_id,                             2
         sum(case when event = 'buy'
                  then 1
                  else 0 end) as conversion
  from collector_log
  group by session_id
 ) c

Nói chung là cũng khá thú vị =.=

Có nhiều đoạn code lắm nhưng tớ cũng chưa xem kỹ.

Tớ cũng bất ngờ vì họ phải code tay như thế thay vì dùng qua ORM các thứ.

Cơ mà ORM thì đúng là có lẽ chỉ lấy được thông tin cơ bản cho dễ dùng thôi.

Còn phân tích thì nên viết 1 lệnh SQL riêng của mình -.-

Code SQL cho phần monitor này thì sẽ có hết trong file này

https://github.com/9health/moviegeek/blob/master/analytics/views.py

Tớ cũng chưa xem kỹ lắm nhưng mà cũng thấy khá là thú vị.

Để xem được phần phân tích thì vào trang này (chưa có link ở trang chủ @@, chắc tớ sẽ sửa front-end để thêm vào, lại thêm 1 issue nữa ở đây)

http://ninehealth.westus.cloudapp.azure.com:8080/analytics

Tớ thấy trong này cũng ra con số nhưng mà cũng chưa kiểm tra kỹ xem đúng hay không =.=

Do đã dùng hết thời gian 2 tiếng rồi nên là tớ định dành để hôm sau kiểm tra kĩ hơn...

Nói thêm về liveBook trên Manning

Lúc mà đọc trên này tớ thấy khá là khó hiểu dòng code python3 populate_logs.py.

Không hiểu cái này có cần để làm cho phần mà hiển thị trong User chạy đúng không.

Không biết cái này nên chạy ở đầu hay chạy ở cuối =.=

Vậy là tớ thử search ở trang Manning và aha mình search đúng keyword thì nội dung sẽ hiện ra đầy đủ hết mà không bị lock @@, không cần phải bỏ tokens ra mua ý.

Hay thật!!!

Quang có thể thử bằng cách gõ chữ populate_logs.py ở trong trang liveBook quyển PRS!!!

Vậy là sau khi đọc được phần text miêu tả 1 cách free.

Tớ hiểu là cái này mình không chạy cũng được =.=

Populate dịch nôm ra nghĩa là lấp đầy (từ population thì là dân số :-?). Đại khái là kiểu log mà mình chưa có thì mình thêm dữ liệu giả vào để xem kết quả sẽ như thế nào!!!

Vì thế nếu mình chưa có thì nên chạy, nếu có rồi thì thôi!!!

Cách hiển thị này của Manning rất là thông minh luôn =.= Thông minh hơn cả Google Books ý. Thế này mới gọi là eBook chứ hix

Okay thì tớ thấy cái này hay quá thì đọc đọc xem còn chú ý gì nữa không.

À nghe họ bảo thì tới Chương 4 chạy cái gì đó trang User mới hiển thị đúng hix. Tớ đang đọc Chương 3 nên chưa mò vào Chương 4...

Trong kết quả tìm kiếm trên có 1 đoạn code rất là lạ ở Chương 4

python –m builder.implicit_ratings_calculator

Tớ tò mò quá thì tìm hiểu implicit rating là gì.

Tớ lại dùng tính năng search của liveBook để tìm hiểu khái niệm đấy =.=

Như đã nói ở trên, Manning sẽ hiển thị nội dung của những gì liên quan đến khái niệm đấy mà không lock =.=

Tớ có thể đọc những đoạn text đấy thay vì đọc cả quyển sách để nắm khái niệm đó =.=

Hóa ra là có 2 kiểu rating

Cái này họ có nhắc từ Chương 2 rồi thì phải nhưng sách bị lock nên tớ chưa đọc tới phần đấy =.=

Hóa ra kiểu mà thu thập hành vi người dùng 1 cách âm thầm thì gọi là implicit.

Còn kiểu thu thập dựa vào người dùng đánh giá item đấy 1 sao hay 5 sao thì gọi là explicit.

Tác giả có xu hướng theo trường phái implicit nhiều hơn vì cũng không tin lắm vào explicit rating vì có thể người dùng không hiểu mình rating có đúng hay không nữa kiểu thế =.=

Tất nhiên là cũng implicit rating cũng vẫn có thể sai cơ mà ít hơn @@.

Tớ còn đọc thêm về 1 khái niệm nào đó mà không nhớ nữa =.=

Tạm thời dừng ở mức đấy đã. Next task có lẽ xem code phần analytics app trên Django như thế nào @@.

Công nhận viết code SQL và hiển thị lại trên web làm cho thông tin mình trực quan hơn nhiều!!! Tất cả live hết

À còn 1 cái nữa là sách này cũng hỗ trợ phần comment

Quang có thể vào trang liveBook của quyển PRS và ấn vào Chương 3

https://livebook.manning.com/book/practical-recommender-systems/chapter-3/

Sau đó sẽ thấy có số 8 và hình kiểu bong bóng dưới tiêu đề Chương 3 ý.

Ấn vào đấy và xem 8 comments =.=

Nhiều câu hỏi hay phết và tác giả cũng trả lời đầy đủ.

Nhờ cái này tớ mới hiểu hơn về script populate_logs.py

Chà còn 1 cái trong comment nữa là populate_ratings.py

Thôi tớ đọc kỹ hơn sau vậy =.= Haizzz

Về thời gian biểu của tớ

Thì sáng hôm qua tớ ngồi xong 2 tiếng là 8 giờ hơn. Mẹ tớ thì qua vẫn ở quê.

Tớ ngồi lên mạng tìm hiểu một lúc về DPI các thứ tới 9h để làm sao cho ảnh screenshot chụp trên macOS nhỏ hơn.

9h30 tớ ăn sáng xong đợi máy laptop đang sạc thì gọi điện cho 1 em đồng nghiệp cũ đang onsite 1 mình ở bên Nhật, Fukuoka.

Tưởng nói ngắn thui mà cuối cùng nói mới tới 11h30 mới xong @@. Bên Nhật lúc ý là 13h30 chiều rồi @@.

Chủ đề nói về công ty outsource, công ty product, Infineon, Bosch, cuộc sống, lựa chọn, benefits =.=

Xong tớ đói qúa ăn bánh mỳ với pa-tê và thêm cả khế nữa.

12h30 ăn xong tớ đi ngủ.

Ngủ mơ màng mà hình như cũng chưa muốn dậy vì mệt và vì sáng dậy sớm buồn ngủ nữa T_T.

15h thì mẹ tớ từ quê lên bấm chuông reo to lắm @@. Thế là tớ tỉnh dậy luôn.

Tớ ngồi viết file note gặp chị Chuyên gia Tâm lý kia tới tận 20h @@.

Mẹ tớ về cũng mệt, ngồi nghịch điện thoại tới 17h rồi đi gội đầu.

Rồi làm các thứ mãi tới 20h30 mới được ăn cơm @@.

22h tớ rửa bát xong rồi định lôi máy tính ra nhưng mệt quá nên thôi =.=

23h xem phim xong thì phơi quần áo =.= rồi đi ngủ.

Sáng nay tớ dậy sớm nhưng mà có khi tớ off ngày hôm nay để làm mấy thứ khác hix.

6h sáng nay thì tớ ngồi copy hết ảnh của mẹ từ iPhone ra vì là bộ nhớ iPhone sắp đầy rồi :( 111GB/128GB rùi :(.

Tớ mà không làm thì ai giúp mẹ.

Rồi tớ copy hết cả đống Memories mà tạo từ ảnh ra trên iPhone ý vì xóa ảnh đi là sẽ mất hết :(.

Mấy cái Memories ý đẹp lắm.

Xong hết mọi thứ là 9h30 sáng @@. Hôm nay mồng 1 nên mẹ tớ đi chùa trước rồi :-S.

Chiều tớ còn phải viết mấy cái email nữa đi đòi tiền với xin giúp đỡ :( mà không biết được hay không.

Sáng mai thì mẹ tớ đi Hòa Bình với chỗ V3 - HVKTQS thì phải để kỷ niệm ngày 22/12 thì phải @@.

Cơ mà không biết mấy giờ đi.

Khả năng thì sáng mai chắc tớ họp online với Quang và anh Công được đấy hix.

Quang gửi meeting request cho tớ nhé...

Thanks Quang....

Giừo tớ đi ăn cơm trưa đây!!!

Cẳm ơn Quang nhiều.

Chúc Quang và gia đình Noel vui vẻ!!!

À còn 1 cái nữa là chắc tớ sẽ nhờ Quang tắt cái MFA (Multi-factor Authentication) đi trên M365 đi vì mỗi lần login nhập cái số từ Authenticator mất thời gian lắm =.= Lại phải lôi điện thoại ra hix. Cái này hình như default là enabled thì phải.

Có gì tớ sẽ email sau!!! Thanks Quang!!!

Còn buổi họp với Microsoft về Azure hôm trước có 2 câu hỏi cuối không có trong file chat chắc tớ sẽ phải viết ra để nhỡ sau này dùng thì...

9health commented 1 year ago

Hello @quangvv9Life,

Công nhận qua tớ dành thời gian để copy hết ảnh của mẹ từ iPhone ra là hợp lý thật.

Giờ lại còn trống thêm 70GB rùi O_O.

Hôm nay mẹ tớ đi chơi chỗ Hòa Bình với cam gì đó chắc là sẽ chụp nhiều ảnh lắm.

Sáng nay thì mẹ tớ 5 giờ đã dậy rồi và 6 giờ kém 15 đi rồi.

Tớ cũng dậy lúc đấy và đọc chương 3 luôn.

Về Chương 3 ở Manning

Thật sự thì hôm nay tớ cũng không dùng tính năng đọc miễn phí 5 phút nữa mà tập trung chủ yếu vào xem đọc code để hiểu hơn về phần monitor (quan sát) hay analytics của MovieGEEKs thế nào.

Thật sự thì rất cảm ơn tác giả đã cho code là free và sách thì mất tiền thôi.

Cơ mà như tớ nói là sách đọc kiểu này cũng gần như cho không rồi hix.

Bác tác giả tớ có xem là làm ở Shopify là kiểu là cung cấp trang web cho những người muốn làm e-commerce các thứ ý và bác ý làm trong nhóm Recommender System (RecSys) thì phải.

Vào link Twitter của bác ý thì cũng thấy là có hội thảo RecSys gì đó tổ chức hàng năm.

https://twitter.com/kimfalk

Giờ thì bác ý còn đang viết tập 2 cho quyển PRS vào buổi tối nữa @@.

Công ty Shopify thấy headquarter ở Canada nhưng cảm giác cứ như là ở châu Âu vậy :-?. Cananda trước là thuộc địa của Pháp nhỉ :-?.

Tớ thấy cũng rất là lạ khi ban ngày bác ý làm data scientist mà buổi tối về lại có cả thời gian viết sách được @@.

Như tớ hồi xưa ở Nhật nếu mà có ai định hướng chắc cũng sẽ làm như thế :-? Mỗi buổi tối có 2 tiếng mà. Cơ mà mình toàn làm linh tinh.

Chắc là bác ý làm ở Anh thì phải cuộc sống cũng balance và có lẽ người ta cũng không sợ lộ các bí mật gì cả vì nói thật để bắt chước được 1 hệ thống thế tớ thấy cũng khó lắm =.=

Và ở công ty châu Âu cũng hay có kiểu trao đổi kinh nghiệm bằng paper hay là các slide ý.

Paper ở đây cũng không quá là học thuật đâu mà kiểu thiên về có hướng gì mới lúc đi làm và thấy đôi. Chia sẻ để industry của ngành đấy cùng đi lên tất cả @@.

Slide kiểu như cũng là 1 dạng như thế vậy :-?

Thường paper có trước và slide đi kèm paper giải thích rõ hơn ^_^

Chết nói sâu xa quá vì lúc tớ đang ngồi đọc code trên GitHub thấy mấy đoạn commit có tên bác ý, tớ ấn vào GitHub của bác ý rồi ấn vào Twitter và đọc thôi O_O.

Về database của Analytics app

https://github.com/9health/moviegeek/blob/master/analytics/models.py

sqlite> SELECT * FROM analytics_rating LIMIT 10;

id          user_id     movie_id    rating      rating_timestamp     type      
----------  ----------  ----------  ----------  -------------------  ----------
1           1           0114508     8           2013-10-05 21:00:50  explicit  
2           2           0499549     9           2013-08-17 15:26:38  explicit  
3           2           1305591     8           2013-08-17 12:28:27  explicit  
4           2           1428538     1           2013-06-15 14:38:09  explicit  
5           3           0075314     1           2020-07-23 01:42:04  explicit  
6           3           0102926     9           2020-05-22 11:46:56  explicit  
7           3           0114369     10          2020-08-16 05:22:27  explicit  
8           3           0118715     8           2020-07-29 07:13:18  explicit  
9           3           0120737     8           2020-09-05 11:52:00  explicit  
10          3           0208092     5           2020-04-09 21:01:12  explicit  

Như Quang thấy ở trên thì đây chính là dữ liệu mà hiển thị ở trang Analytics của MovieGEEKs web app.

Có thể thấy dữ liệu này có từ rất lâu rồi @@.

Và là dữ liệu này lấy từ ở bên trang The Movie Database nữa!!!

Công nhận có 1 trang có dữ liệu, có rating open-source để nghiên cứu cũng hay ghê.

Không biết bên food có cái nào như thế không. Tớ cũng nhắn đến 1 lần rùi. Có lẽ tìm sẽ ra thôi!!!

Dữ liệu của TMDB còn được đưa lên trang Kaggle để nghiên cứu luôn!!!

https://www.kaggle.com/datasets/tmdb/tmdb-movie-metadata

sqlite> SELECT COUNT (*) FROM analytics_rating;

COUNT (*) 
----------
921398    

Tớ cũng thấy cái này có lẽ sẽ có nhiều data đây nên thử count xem như thế nào.

Và aha có tận hơn 900K dòng, nhiều thật đấy =.=

Không hiểu cái SQLite3 chịu nổi nhiệt không nhưng mà thấy đáp ứng vẫn có vẻ tốt.

Có lẽ là do back-end của Azure tốt. Tớ đang dùng ổ Premium SSD P6 64GB. Hình như cũng thuộc loại gần xịn nhất rồi =.= I/O latency thấp mà băng thông cao nữa =.= HDD chắc không được thế đâu...

Với cả chip vCPU 1 core thôi nhưng mà là dòng Xeon ra đời ngang với chip Intel đời 8 thì phải :-? Cũng khá là nhanh.

sqlite> PRAGMA table_info(analytics_rating);

cid         name        type        notnull     dflt_value  pk        
----------  ----------  ----------  ----------  ----------  ----------
0           id          integer     1                       1         
1           user_id     varchar(16  1                       0         
2           movie_id    varchar(16  1                       0         
3           rating      decimal     1                       0         
4           rating_tim  datetime    1                       0         
5           type        varchar(8)  1                       0         

Tiếp tới tớ xem thông tin chi tiết các cột trong bảng analytics_rating như thế nào.

sqlite> SELECT * FROM analytics_rating WHERE type="implicit";

Tớ thử tìm xem ở cột type liệu có cái gì khác explicit không cơ mà thực sự là không có gì haizzzz.

sqlite> SELECT COUNT(DISTINCT user_id) FROM analytics_rating;

COUNT(DISTINCT user_id)
-----------------------
71707                  

Tớ đếm thử xem có bao nhiêu unique user ở trong table đấy và ra là hơn 70K.

Trung bình thì 1 user sẽ xem là 900K/70K ~= 13 bộ phim.

Thế mới thấy bên TMDB có nhiều người dùng thế nào và họ chịu rating thế nào (chắc là không phải user giả đâu Quang ạ, đã free rồi còn làm kiểu dummy user làm gì đúng không???)

Để rating thì tớ nghĩ chắc họ cũng phải xem phim này chứ dựa vào poster mà rating thì cũng hơi sao sao thật @@.

Tớ thì xem phim xong hay mua đồ gì xong trên Amazon chẳng hạn cũng chả bao giờ rating T_T. Tớ lười quá.

Có lẽ kiểu thế hệ Gen Z hay sau Gen Z chắc là thích rating hơn.

Ví dụ như trên Foody chẳng hạn. App đấy tớ nghe quanh quanh từ hồi 2014.

Cứ đi ra đường muốn ăn gì là mọi người lại lên Foody.

Ngoài cơ sở dữ liệu tốn rất nhiều công thu thập ra và còn nhiều hơn cả Google Maps.

Ở nước ngoài thì Google Maps họ có cái xe riêng hay thuê người riêng để đi chụp ảnh và thu thập nhưng ở Việt Nam do loằng ngoằng quá nên là mọi người tự làm hết thành ra database cũng không quá là mới.

Thường tìm quán cafe nào mà khó tìm thì trên Foody có hết.

Cơ mà Google Maps chưa chắc có.

Ở Nhật thì ngược lại @@, trên Google Maps có hết và tớ cũng hay dùng vì có tiếng Anh.

Cũng có 1 trang riêng của Nhật về list các chỗ ăn uống và có review đàng hoàng mà tớ quên tên rồi =.= Xưa các bác ở chỗ Yamanashi đặt chỗ ăn toàn vào trang đấy...

sqlite> SELECT * FROM analytics_rating ORDER BY id DESC LIMIT 10;

id          user_id     movie_id    rating      rating_timestamp     type      
----------  ----------  ----------  ----------  -------------------  ----------
921398      71707       1623205     6           2013-03-09 12:37:35  explicit  
921397      71706       0414387     10          2020-04-17 07:17:32  explicit  
921396      71706       0172495     10          2020-04-17 07:03:35  explicit  
921395      71705       9898858     3           2020-04-04 00:00:52  explicit  
921394      71705       9893250     10          2021-02-20 21:45:51  explicit  
921393      71705       9784456     6           2020-07-27 00:40:13  explicit  
921392      71705       9777644     5           2020-06-14 22:54:28  explicit  
921391      71705       9770150     3           2021-02-21 22:01:39  explicit  
921390      71705       9686708     5           2020-07-01 22:55:58  explicit  
921389      71705       9620288     6           2021-11-23 22:33:15  explicit  

Tớ thử xem những row cuối cùng là người ta log khi nào.

Có vẻ như là cũng không quá mới @@. Lẽ ra dữ liệu này tớ nghĩ năm 2022 thì đúng hơn.

Chắc là có 1 vấn đề gì đó vì tớ có search phim Wakanda 2 trong này cũng không thấy luôn.

Có lẽ script lúc chạy có vấn đề gì đó ^_^

sqlite> SELECT COUNT (DISTINCT movie_id) FROM analytics_rating;

COUNT (DISTINCT movie_id)
-------------------------
38018                    

Tớ cũng kiểm tra thử xem là có bao nhiêu bộ phim ở trên TMDB, cũng khá là nhiều, khoảng hơn 40K phim.

Không hiểu phim Mỹ nhiều đây hay là phim Ấn =.= Ấn nhiều phim lắm ý.

sqlite> SELECT * FROM analytics_cluster;

Tớ xem thử có dữ liệu trong bảng analytics_cluster không thì chả thấy gì cả. Chắc là phải chạy script nào đó thì mới có dữ liệu...

Về API được gọi ở trang Analytics

Tớ thử vào trang analytics của MovieGEEKs ở đây

http://ninehealth.westus.cloudapp.azure.com:8080/analytics

Và tất nhiên lại dùng công cụ Firefox Web Developer Tools để xem kỹ hơn rồi.

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/api/get_statistics?date=2022-12-24

{
    "items_sold": 8,
    "conversions": 33,
    "visitors": 9,
    "sessions": 9
}

Đầu tiên là API để lấy dữ liệu ra hiển thị các mục như bao nhiêu phim được bán, bao nhiêu người bị quy phục, bao nhiêu người vào website và có bao nhiêu session.

Con số này có vẻ cũng chưa đúng lắm và tớ định kiểm tra lại trong code nhưng mà vẫn chưa làm hix =.=

Thôi cứ để tạm đấy kiểm tra sau vậy hix.

Không biết lệnh SQL của bác ý viết có gì sai không -.-

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/api/events_on_conversions

[
    {
        "conversion": "No Buy",
        "event": "details",
        "count_items": 31
    },
    {
        "conversion": "No Buy",
        "event": "genre:Action",
        "count_items": 1
    },
    {
        "conversion": "No Buy",
        "event": "genre:Biography",
        "count_items": 1
    },
    {
        "conversion": "No Buy",
        "event": "genre:Comedy",
        "count_items": 3
    },
    {
        "conversion": "No Buy",
        "event": "genre:Documentary",
        "count_items": 1
    },
    {
        "conversion": "No Buy",
        "event": "genre:Film-Noir",
        "count_items": 1
    },
    {
        "conversion": "No Buy",
        "event": "genre:History",
        "count_items": 1
    },
    {
        "conversion": "No Buy",
        "event": "genre:Short",
        "count_items": 2
    },
    {
        "conversion": "No Buy",
        "event": "genre:War",
        "count_items": 1
    },
    {
        "conversion": "No Buy",
        "event": "more_details",
        "count_items": 8
    },
    {
        "conversion": "Buy",
        "event": "buy",
        "count_items": 38
    },
    {
        "conversion": "Buy",
        "event": "details",
        "count_items": 207
    },
    {
        "conversion": "Buy",
        "event": "genre:Action",
        "count_items": 1
    },
    {
        "conversion": "Buy",
        "event": "genre:Adventure",
        "count_items": 7
    },
    {
        "conversion": "Buy",
        "event": "genre:Comedy",
        "count_items": 6
    },
    {
        "conversion": "Buy",
        "event": "genre:Fantasy",
        "count_items": 1
    },
    {
        "conversion": "Buy",
        "event": "genre:Game-Show",
        "count_items": 1
    },
    {
        "conversion": "Buy",
        "event": "genre:Music",
        "count_items": 6
    },
    {
        "conversion": "Buy",
        "event": "genre:Short",
        "count_items": 1
    },
    {
        "conversion": "Buy",
        "event": "genre:Talk-Show",
        "count_items": 6
    },
    {
        "conversion": "Buy",
        "event": "genre:War",
        "count_items": 7
    },
    {
        "conversion": "Buy",
        "event": "more_details",
        "count_items": 51
    },
    {
        "conversion": "Buy",
        "event": "save_for_later",
        "count_items": 30
    }
]

Đây là các API dùng để hiển thị xem có bao nhiêu người mua và không mua.

Tớ cũng chưa hiểu rõ lắm. Có lẽ Quang nhìn vào cái hình đấy thì sẽ hiểu rõ hơn tớ =.=

Tớ không chuyên phân tích lắm...

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/api/ratings_distribution

[
    {
        "rating": 0,
        "count_items": 281
    },
    {
        "rating": 1,
        "count_items": 10814
    },
    {
        "rating": 2,
        "count_items": 9223
    },
    {
        "rating": 3,
        "count_items": 15487
    },
    {
        "rating": 4,
        "count_items": 28193
    },
    {
        "rating": 5,
        "count_items": 69747
    },
    {
        "rating": 6,
        "count_items": 120370
    },
    {
        "rating": 7,
        "count_items": 206680
    },
    {
        "rating": 8,
        "count_items": 222146
    },
    {
        "rating": 9,
        "count_items": 130106
    },
    {
        "rating": 10,
        "count_items": 108351
    }
]

Còn đây là dữ liệu để hiển thị phân phối ratings của các phim.

Screenshot 2022-12-24 at 08-43-05 MovieGEEKs

Có vẻ như cũng đúng khi mà phân phối này cũng hao hao phân phối chuẩn. Điểm 7 và 8 là nhiều nhất :-?

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/api/top_content

[
    {
        "content_id": "10295212",
        "title": "Shershaah ",
        "sold": 2
    },
    {
        "content_id": "0993840",
        "title": "Army of the Dead ",
        "sold": 1
    },
    {
        "content_id": "10329614",
        "title": "Censor ",
        "sold": 1
    },
    {
        "content_id": "13863968",
        "title": "The Wisdom of Trauma ",
        "sold": 1
    },
    {
        "content_id": "3110958",
        "title": "Now You See Me 2 ",
        "sold": 1
    },
    {
        "content_id": "3480822",
        "title": "Black Widow ",
        "sold": 1
    },
    {
        "content_id": "4876134",
        "title": "The Misfits ",
        "sold": 1
    }
]

Còn đây là API lấy ra các bộ phim được mua nhiều nhất bởi người dùng ở trang web MovieGEEKs này @@.

Cứ ấn nút Buy không mất tiền là phim ý sẽ vào top ^_^

Công nhận là Buy kiểu này cũng hay ghê :D. Nhẹ nhàng ghê chứ không bị charge vào credit card ^_^

Ấn nút này cũng có cảm giác hay hơn là rating vì rating phải chọn từ 1 tới 10 cũng rất là khó @@.

Buy thì chỉ có kiểu như là Like hay không Like thôi ^_^

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/api/clusters

{
    "cluster": []
}

API này thì không trả ra gì cả @@.

Nay Quang có hỏi tớ sáng họp là quyển sách này có tất cả bao nhiêu API @@.

Từ từ tớ sẽ làm tài liệu để cho Quang xem nhé @@. Cũng không quá nhiều đâu...

Còn về câu hỏi là đọc chương ý xem liên quan gì tới cái mình làm hãy nên đọc thì câu đấy có vẻ chung chung quá @@.

Nói thật tớ không trả lời được câu hỏi chung chung kiểu như thế @@. Có lẽ chung chung với tớ thôi còn với Quang thì Quang đủ khả năng nhận ra =.=

Tớ không giỏi mấy môn xã hội lắm mà, không giỏi nhận biết cảm xúc nữa =.=

Về code Python và html cho Analytics app

Tớ thì chỉ chú ý tới phần URL như thế nào thui

https://github.com/9health/moviegeek/blob/master/prs_project/urls.py

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^movies/', include('moviegeeks.urls')),
    url(r'^collect/', include('collector.urls')),
    url(r'^analytics/', include('analytics.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^rec/', include('recommender.urls'))

Đây là URL chung của tất cả các trang trên MovieGEEKs

https://github.com/9health/moviegeek/tree/master/analytics

Đây là trang chứa code của phần Analytics app cho back-end. Nếu vào views.py sẽ thấy rất nhiều lệnh SQL được bọc @_@.

Đây là phần front-end của trang Analytics chung và cho user nữa

https://github.com/9health/moviegeek/blob/master/templates/analytics/index.html

Quang có hỏi tớ tại sao là user khi mình click vào ở góc trên cùng bên trái đồ thị lại không hiển thị gì???

Nguyên nhân là do user đấy không có trong bảng analytics_rating nên không hiển thị ra gì đấy =.=

Chỉ có user ở bên TMDB mới hiển thị ra thôi hoặc là user mình thêm vào qua script ý =.=

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/user/3/

Thế là tớ thử xem user ở TMDB thì như thế nào. Tớ thay thử xem user có số 3 ở cuối và aha ra được list các phim user này thích rồi, hay quá!!!

Screenshot 2022-12-24 at 08-36-11 MovieGEEKs

Tớ mò tiếp xuống dưới thì thấy hiển thị ra các user giống như user này mà người ta giọ là taste (vị) giống nhau ý như ở trong chương 3 có đề cập

Screenshot 2022-12-24 at 08-36-20 MovieGEEKs

Hình này thì Figure 3.9. Chart of users’ tastes, tác giả muốn nói là user nào mà có taste giống nhau thì khả năng cũng thích phim mà user có vị (taste) giống mình đó xem @@.

Về debug log lúc chạy server

December 24, 2022 - 01:24:55
Django version 2.2.27, using settings 'prs_project.settings'
Starting development server at http://0.0.0.0:8080/
Quit the server with CONTROL-C.

[24/Dec/2022 01:25:14] "GET /analytics HTTP/1.1" 301 0
[24/Dec/2022 01:25:14] "GET /analytics/ HTTP/1.1" 200 7184
[24/Dec/2022 01:25:15] "GET /static/js/collector.js HTTP/1.1" 200 618

[24/Dec/2022 01:25:16] "GET /analytics/api/clusters HTTP/1.1" 200 15
[{'conversion': 'No Buy', 'event': 'addToList', 'count_items': 8310}, {'conversion': 'No Buy', 'event': 'details', 'count_items': 41927}, {'conversion': 'No Buy', 'event': 'genreView', 'count_items': 13407}, {'conversion': 'No Buy', 'event': 'moreDetails', 'count_items': 20047}, {'conversion': 'Buy', 'event': 'addToList', 'count_items': 1703}, {'conversion': 'Buy', 'event': 'buy', 'count_items': 1134}, {'conversion': 'Buy', 'event': 'details', 'count_items': 8589}, {'conversion': 'Buy', 'event': 'genreView', 'count_items': 2781}, {'conversion': 'Buy', 'event': 'moreDetails', 'count_items': 4213}]

[24/Dec/2022 01:25:17] "GET /analytics/api/events_on_conversions HTTP/1.1" 200 603
[24/Dec/2022 01:25:17] "GET /analytics/api/get_statistics?date=2022-12-25 HTTP/1.1" 200 70
Not Found: /favicon.ico
[24/Dec/2022 01:25:17] "GET /favicon.ico HTTP/1.1" 404 2554
[24/Dec/2022 01:25:17] "GET /analytics/api/ratings_distribution HTTP/1.1" 200 410

Trên này có một lỗi là file favicon.ico không tìm thấy. Nhìn khó chịu thật @@.

File này thực ra tạo cũng dễ thui hix O_O.

Ngoài ra thì có thể thấy các API được gọi từ front-end xuống back-end ở đây O_O.

Về script populate_logs.py

Nội dung script thì nằm ở đây

https://github.com/9health/moviegeek/blob/master/populate_logs.py

Nói thật là tớ cũng không định đọc đâu nên tớ chạy thôi xem như thế nào.

Lệnh chạy thì đơn giản thôi

(venv_3.6.9) ninehealth@LinuxVM15:~/work/moviegeek$ python3 populate_logs.py     

user id 400005 selects film 4172430 and details
user id 400005 selects film 2140479 and details
user id 400003 selects film 3110958 and details
user id 400005 selects film 2582782 and details
users

user with id 400001

 885441: ['2937696']
 885444: ['3874544']
 885445: ['3949660']
 885459: ['1878870']
 885462: ['3774114']
 885473: ['1711525']

Phía dưới lệnh chạy là các log xổ ra đấy.

Cơ mà tớ đợi mãi, đợi mãi mà chưa thấy xong @@.

Thế là thôi quay ra đọc nội dung cái file Python đấy như thế nào mà sao chạy lâu thế =.=

    Log.objects.all().delete()
    random.seed(SEED)

    number_of_events = 100000

    print("Generating Data")
    users = [
        User(400001, 20, 30, 50),
        User(400002, 50, 20, 40),
        User(400003, 20, 30, 50),
        User(400004, 100, 0, 0),
        User(400005, 0, 100, 0),
        User(400006, 0, 0, 100),
    ]
    print("Simulating " + str(len(users)) + " visitors")

    for x in range(0, number_of_events):
        randomuser_id = random.randint(0, len(users) - 1)

À chạy lâu là vì vòng lặp for tận 100K lần kia kìa do biến number_of_events đặt là 100000 haizzzz.

Tầm 20 phút mới xong thì phải, lâu ghê...

Sau khi chạy hết xong rồi thì tớ vào trang Analytics và ra hình giống tác giả.

Figure 3.11. MovieGEEKs analytics dashboard

https://drek4537l1klr.cloudfront.net/falk/Figures/03fig11_alt.jpg

Thú thật là tớ không thích lắm kết quả thế này mặc dù nhìn nó đẹp và đúng với lý thuyết thật =.=

Cơ mà trông kiểu nó giả tạo làm sao ý =.=

Đây là kiểu user giả sinh ra những cái sự kiện như thế và log vào database :(.

Nhìn chả giống ngoài đời gì cả.

Nếu mà dùng để test xem hiển thị đúng hay không thì okay =.=

Chứ dùng mà để phân tích website thì chết =.= Phân tích là nên dựa vào con số thật, đời thật, tớ nghĩ thế :|.

Về cách hoạt động script populate_logs.py

Thật sự là tớ khá bất ngờ vì sao dùng lệnh trên mà lại tạo ra user giả, tạo ra comment giả và commit vào database được @@.

Vì thường tớ nghĩ code thì phải compile các thứ và đủ các thứ option thì mới làm được cơ :-?

Hóa ra code này cũng có cái gì đấy chỉ dùng những thư viện nào mà cần thôi.

Python hay thật @@

import datetime
import os
import random

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'prs_project.settings')

import django

django.setup()

from collector.models import Log

SEED = 0

Đây là phần import các thư viện của Python và Django.

Đồng thời cũng import luân cả models trong Collector App nữa.

Vậy là mình có thể commit vào database rồi!!!

Hay ghê!!!

class User:
    sessionId = 0
    userId = 0
    likes = {}

Đây là class tác giả tự định nghĩa dùng cho file này.


def select_film(user):

    genre = user.select_genre()
    interested_films = films[genre]
    film_id = ''
    while film_id == '':
        film_candidate = interested_films[random.randint(0, len(interested_films) - 1)]
        if film_candidate not in user.events[user.sessionId]:
            film_id = film_candidate

    return film_id

Đây là hàm tác giả tự định nghĩa dùng cho file này.


def main():
    Log.objects.all().delete()
    random.seed(SEED)

    number_of_events = 100000

Đây là hàm chính.

if __name__ == '__main__':
    print("Starting MovieGeeks Log Population script...")
    main()

Đây là phần để Python gọi hàm chính ra.

Nhìn cách viết đoạn chương trình lồng trong 1 cái MovieGEEKs web app mà không bị ảnh hưởng gì tớ thấy rất là hay luôn @@.

Mình không cần phải nghĩ quá sâu xa gì về OOP hay là design pattern cả.

Cứ vận dụng cách mà tác giả làm thôi.

Đơn giản và ai cũng có thể làm được.

Ngoài ra thì mọi người cũng tránh sửa file của nhau nữa @@.

Tớ thấy cái này cũng có thể áp dụng để kiểm tra database của food app mà Quang sắp dựng lên ý @@.

Ví dụ như có thể có 1 file check_food_database.py ở cùng level đấy chẳng hạn.

Quang tự define class, function dùng và có các lệnh để test xem database model tạo đúng hay chưa...

Còn nếu làm chỉnh chu hơn thì tạo hẳn 1 folder mới và để file Python kia ở trong đấy rùi chạy :-?

Tớ cũng chưa nghĩ ra thế nào, chỉ ý tưởng thôi cơ mà thấy cách các môi trường lồng vào nhau thế này và không bị ảnh hưởng bởi nhau rất là hay.

Ai dùng cái gì thì gọi cái đấy ^_^

Hoặc là do tớ đọc chầm chậm nên mọi thứ dễ vào hơn nên thấy hay =.=

Chứ cứ đọc ào ào có khi tớ không nhận ra cái hay của code bác ý @@.

Về Microsoft 365 security

Hình như Quang chỉ cần đọc một tin nhắn của tớ claim về cái security của Microsoft 365 thôi là Quang đã hiểu và disable luôn rồi thì phải @@.

Thanks Quang nhiều nhé hix. Quang mà có bật lên theo kiểu user của Quang ý thì Quang vẫn có thể bật được đó!!!

Tớ thì ngại bật cái ý vì hôm nào tớ cũng gõ email (username) và password để đăng nhập mà @@. Tớ thích dùng Private Mode hix =.=

Với cả gõ lại password nhiều mình cũng training kiểu nhớ theo như là muscle brain ý Quang.

Xưa tớ vào công ty cũ được cho 1 cái password cực kì khó nhớ luôn nhưng mà sau 1 tuần cứ gõ đi gõ lại thành ra tạo thành 1 cái pattern trong não và nhớ luôn :D.

Gõ nhiều cũng là 1 cách học thuộc lòng password đơn giản ^_^

Ví dụ password từ năm 2016 của tớ đây (giờ tớ không còn dùng nữa ^_^): Rc8Bp6Ua7

Đấy họ cho cái password này kèm email đấy =.=

Hình như sau có đợt password bị đổi thành ít nhất 12 kí tự mà tớ không chịu đổi vì bận dự án quá thành ra bị lock account =.= Thế là lại phải reset password phát nữa.

Tớ không nhớ lần này reset password thành cái gì nữa =.= Cơ mà tớ cũng dùng password ý được 2 năm :-?

Ở công ty mà tớ remote onsite bên Sing cung cấp chip cho cả trăm triệu thẻ CCCD ở Việt Nam thì rule đặt password của họ rất kinh khủng. Phải có đủ 16 ký tự trở lên và rất là loằng ngoằng nữa =.=

Tips của họ là nhớ 1 câu tiếng Anh gì đó và chuyển chữ cái trong ý thành số cơ mà nói thật tớ chịu không làm được =;=

Tớ lại modify cái password ban đầu họ đưa cho tớ =.=

Về Azure

Nói đến cái Microsoft 365 thì tớ nhớ tới Azure.

Tớ đang băn khoăn là mình nên đăng ký theo kiểu là dùng account @outlook.com hay account @subdomain.onmicrosoft.com.

Nguyên nhân là hôm trước xem hướng dẫn của họ nói về Active Directory mà thật sự vẫn chưa hiểu lắm.

Có 1 slide hay nói về những ai không redeem được benefit đấy.

Ví dụ như tớ đang dùng offer 12-month free chẳng hạn thì không thể redeem được rồi.

Cơ mà nếu dùng email @outlook.com liệu có được không?

Tớ thấy nếu mà dùng account @subdomain.onmicrosoft.com của họ có vẻ hợp lý hơn.

Cơ mà lại có 1 cái nếu dùng cái đấy thì sau 1 năm cái Microsoft 365 hết hạn vì họ cho mình có 1 năm thôi mà =.=

Có thể mình trả lời là nếu mà hết hạn thì mình sẽ bỏ tiền túi ra hay tiền xin từ 1 quỹ đầu tư nào để dùng tiếp Microsoft 365 =.=

Cơ mà thực sự giá gói Business Standard Microsoft tài trợ cho mình cũng khá là đắt so với thị trường chung =.=

$12/user/tháng hix. Họ cho mình tối đa 10 user là $120/tháng và $2400/năm

Khá là ưu ái đối với mình T_T.

Cơ mà đấy là free chứ sau 1 năm liệu tiếp tục được hay không :(.

Liệu mình có chịu bỏ tiền túi ra dùng không khi mà thực sự email, Teams, OneDrive 1TB, Office 365 có thể tìm 1 giải pháp khác hix.

Như ở công ty cũ tớ thì chỉ mua gói email Exchange Online 365 thôi Quang à. Teams và OneDrive 1TB thì đi kèm luôn cái đấy rồi.

Cơ mà Office thì không có đâu. Office là họ mua theo kiểu offline và enterprise nữa nên là activiate bằng server nội bộ công ty. Microsoft muốn biết có bao nhiêu người dùng cũng khó =.= Windows cũng kiểu thế =.=

Đấy thì nếu không có Office 365 thì còn đâu $3/user/tháng hay $6/user/tháng...

Về bài toán kinh tế là như thế đấy =.=

Sau 1 năm nữa thì chắc không còn Teams với OneDrive 1TB, Office 365 có bản quyền đâu nếu mình không renew hix.

Cơ mà công nhận cái này đắt thật đấy. Nếu mà dùng gói Microsoft Family cũng được 6 user, 6 TB cho 6 users, Office 365 thì cũng cho 6 user thì phải =.= Cơ mà giá có $100/year thôi =.=

Chả hiểu sao ông Business Standard kia lại là $2400 cho 10 user/year nữa =.= Đắt gấp 10. Ảo thật mà trong khi vẫn chỉ có Office 365, OneDrive 1TB. Chỉ có hơn 1 cái là Teams cho Business khác Teams cho Personal thôi =.=

Đấy thì tớ cũng đắn đo thế thôi =.=

Quang thử xem cái nào hợp lý thì apply offer Azure nhé.

Xong rồi Quang cũng thử làm quen với phần quản lý trên Azure bằng cách tạo máy ảo như hướng dẫn của tớ trên Wiki GitHub nhé O_O.

Rồi kiểm tra cost nữa...

Thanks Quang nhiều.

À với cả video họp hôm trước của Microsoft Quang nhớ xin sớm nhé vì nghe đâu sau 30 ngày là sẽ bị xóa đấy hix.

Chỉ cần nhờ bác mà invite Quang vào meeting share link để mình download thui!!! Thanks Quang.

Về thời gian biểu của tớ hôm nay

Đấy thì 8 giờ tớ ngồi đọc xong Chương 3 theo kế hoạch 2 tiếng thì đi ăn sáng.

Tớ cũng không thấy Quang nhắn tin với check email trên M365 nên là miss mất cuộc họp :(

Vào muộn, mong mọi người thông cảm hix. Đây là cuộc họp lần thứ 3 vào mỗi thứ 7 rồi nhỉ hix.

Có gì nếu mà tớ quên thì Quang cứ nhắn tớ qua iMessage ý hix hix Thanks Quang nhiều...

Vì tớ lười check email lắm :(.

Họp xong thì tớ ngồi viết 1 cái email cho bạn cấp 2 tớ vụ $15K kia nữa.

Tớ định đi ăn trưa nhưng mà lại lôi bài tập của chị kia ra xem. Tớ ngồi viết cái Future và Ghi Nhận Cảm Xúc tới 13 giờ 50 :(.

Trong lúc đó thì tớ cũng có 1 cái task mà đang đắn đo cho làm là mua cục sạc Anker 10,000 mAh cho mẹ :(

Nói chung là giá cũng rẻ hơn Nhật và Mỹ do đang mùa cuối năm, giảm giá nữa. Ngay trang chủ Anker cục ý có 400K thôi. Cơ mà nhà tớ cũng thiếu dây sạc nên cần thêm 1 cái dây nữa, dây cũng giảm giá 50% còn 200K. =.=

Cơ mà đang khá là đắn đo vì xem là mua xong liệu mình có bị financially collapse không =.=

Thế là tớ cứ nghĩ mãi, định là 13h30 gọi hỏi bên Anker xem họ còn không để mua xong mà thôi.

Có 1 task nữa tớ mới nghĩ ra hôm trước là đọc lại hết đống bảo hiểm nhân thọ M***life mà tớ mua được 2 năm rồi =.= Tớ đang định đòi để cho tình hình tài chính khấm khá hơn =.= Đòi bao nhiêu cũng được =.= Bị mất nhiều thì thôi haizzz.

Đấy là chị họ tớ bảo tớ mua và bán cho tớ luôn @@, chị họ tớ cũng gửi nhiều email lắm về các vấn đề tài chính mà tớ bận dự án quá chưa đọc =.= Tớ định đọc lại hết như thế nào vì xưa chị tớ gửi mà tớ không đọc cũng là kiểu có lỗi thế nào ý. Người ta quan tâm mới gửi email cho mình hix....

Đấy thì tớ ngủ trưa tới 17h mới tỉnh hẳn T_T. Tớ đi lau nhà, dọn dẹp nhà cửa tới 18h15 mẹ đi chơi về.

18h30 đi xe buýt về quê ngoại ở Thanh Oai, Hà Tây và ăn tối với dì và bà lúc 20h10 @@.

Trong lúc ăn tối ngồi xem được chương trình VTV Đặc Biệt nói về kiểu trên mạng họ kiếm tiền như thế nào đấy ở đây. Tớ download xuống luôn rồi @@.

https://www.youtube.com/watch?v=DS4k0EUlCRs&list=PLzc9r8PlgBfeoCT-Wa4bWphgUAZCqiZyA&index=8

Vì tớ thấy bạn mình cũng có vẻ sắp vào hoàn cảnh đấy nên lo lắng quá @@.

Hi vọng là không ai bị như thế nữa hix sau khi xem video trong này.

Tớ cũng thấy tớ sang được Nhật là may mắn thật. Kiếm được tiền nữa @@. Tuy tinh thần bị hành hạ 1 tẹo thôi nhưng so với các em trên bị đánh đập, bị chích điện thì nhẹ nhàng hơn nhiều :(.

Giờ thì tối khuya rồi và tớ cũng đang viết email cho Quang đấy @_@.

Cơ mà nghĩ tới 1 năm tới không biết còn dùng được Microsoft 365 nữa hay không cũng tiếc!!! Thôi cứ làm sao tận dụng được tốt những gì mình đang có vậy!!!

Còn GitHub Enterprise nữa chứ. Hôm trước tớ cũng tìm hiểu rồi thì thấy cái đấy hình như còn không bằng GitHub bình thường ý vì dùng CI/CD còn bị tính xiền @@. Có hơn ở các feature liên quan tới security thui...

Còn Visual Studio Enterprise thì tớ cũng chưa tìm hiểu.

Còn Dynamics 365 chả biết dùng thế nào nữa ý :(

Thôi cứ tập trung cái Python, Django các thứ đã @@.

Giả sử sau có nhà đầu tư mà họ mình tiền dùng tiếp Microsoft 365 cũng tốt cơ mà cái đấy hao tiền thật =.=

Hoặc là thuyết phục Microsoft cho mình dùng thêm 1 năm nữa cơ mà cũng khá là khó...

Ban đầu tớ nghĩ chỉ có Azure thôi ai ngờ còn có thêm benefit này =.=

Thực ra Microsoft họ cũng có thể cung cấp Microsoft 365 cho các tổ chức phi lợi nhuận (non-profit organization NGO) ý. Nghe đâu 1 tổ chức thế được 10 license và dùng mãi mãi @@.

https://nonprofit.microsoft.com/getting-started

https://www.microsoft.com/microsoft-365/nonprofit/plans-and-pricing

Cơ mà thôi cứ kệ vậy, có lẽ là sau này tớ nghĩ Microsoft sẽ extend cái Microsoft 365 thành 4 năm chứ nói thật nếu mà dùng Azure 4 năm mà không dùng Microsoft 365 thì thế nào ấy @@.

Vậy thui.

Một lần nữa cảm ơn Quang nhé.

Sorry tớ nhắn hơi muộn hix. Tớ đang đợi em họ về @@.

quangvv9Life commented 1 year ago

Hi Hải,

Cám ơn Hải đã cố gắng nhắn lại cho tớ mặc dù đã muộn nhé. Tớ đã mua cuốn "Practical Recommender system" trên manning rồi Hải nhé.

image

Hải có thể truy cập bằng account sau để login và đọc livebook nhé : User : nineodin@outlook.com Pass : Aneye4wi$dom

Phần này là TS của công ty nên mình quyết định đầu tư thôi

BR Quang

quangvv9Life commented 1 year ago

Hi Hải,

Về các luồng trao đổi va họp hành của cty mình thì Hải cố gắng vào email : nguyendanghai@9reatodin.onmicrosoft.com thường xuyên hơn để cập nhật kịp thời nhé.

Br Quang

9health commented 1 year ago

Hello @quangvv9Life,

Tình hình là qua tớ ngồi quét sân cho bà ngoại, nhiều lá khô lắm với cả chặt lá chuối khô rùi đốt hết, sau đó tớ còn sang giặt mấy cái thảm, chiếu, dép ở bên nhà dì cùng với dì nữa thành ra hôm nay người ê ẩm luôn @@.

Về thời gian biểu của tớ hôm nay

Tối qua lại còn đi xem chương trình "12 Ngày Đêm - Lằn Ranh Lịch Sử" nữa chứ @@.

https://vtv.vn/video/12-ngay-dem-lan-ranh-lich-su-25-12-2022-596233.htm

Mẹ tớ đòi đi từ 18 giờ để lấy chỗ đẹp cơ mà 20 giờ 10 mới bắt đầu, gần 22h mới xong, 22h15 mới về đến nhà =.=

5 giờ sáng nay thì tớ cũng tỉnh rồi nhưng mà nghĩ là mình hôm qua làm nhiều thứ quá nên cơ thể chắc mệt, dậy chưa chắc làm việc được tốt nên là thôi cứ ngủ đã rồi tính tiếp =.= Quan trọng bây giờ là phục hồi sức khỏe đã hix.

8 giờ kém 15 thì mẹ tớ gọi tớ dậy @@. Ngồi xem lại clip YouTube hôm qua. 9h15 ăn sáng xong, tớ ngồi vào bàn đọc mấy cái Azure các thứ vì hôm trước có comment những thứ mà cũng chưa rõ ràng lắm hix.

Chiều thì tớ đi 1 lúc ra làm thẻ CCCD điện tử với mẹ @@.

Về thì tớ email cho bạn cấp 2 tớ về vụ $15K U S D T hix.

Cái clip hôm trước bị YouTube gỡ xuống rồi @@. Tớ sẽ update lại link mới ở bài viết trước @@.

Bị cảnh cáo như thế 3 lần là sẽ bị xóa tài khoản :( Tớ thấy lo lắm. Vậy là tớ ngồi đọc luôn xem YouTube copyright là như thế nào :(

YouTube Copyright School - YouTube

https://www.youtube.com/watch?v=InzDjH1-9Ns

Nói thật thì rất là loằng ngoằng khi xem kỹ video trên nhưng mà tóm lại cái gì copyrighted rồi thì không được upload lên YouTube kể cả nếu để private vì YouTube là distribution platform thành ra là private thì người khác không kiện được nhưng mà con bot của YouTube vẫn tìm thấy và báo cho người sở hữu bản quyền video đấy T_T.

Tất nhiên là nếu chủ sở hữu bản quyền mà không biết và không kiện thì không sao hix.

Hi vọng là tương lai account YouTube mẹ tớ không sao và tớ cũng sẽ cẩn trọng hơn video upload lên của mẹ tớ hix.

Khi bị remove video như thế cảm giác rất là lo lắng :(. Bao nhiêu công sức mà lại bị removed :(. Nên là bị cảnh cáo là tớ phải kiểm tra và học luôn cho chắc hix.

Tớ định share cho bạn tớ về cái phóng sự VTV Đặc Biệt - Bẫy mà không biết upload lên đâu để share theo kiểu private đi :( Dropbox không được, Google Drive không được.

Thôi còn 1 cách là mã hóa, đặt mật khẩu file .zip rồi upload cho bạn tớ xem vậy.

Đồng thời gửi kèm link VTV ở đây hix

https://vtv.vn/truyen-hinh/xem-lai-vtv-dac-biet-bay-20221224162300588.htm

Thế là tớ cũng bớt lo lắng rùi.

Rồi tiếp theo là đọc email bạn cấp 2 tớ gửi từ hôm T6 mà chưa kịp đọc.

Tớ cũng mất thời gian đọc thông tin, tìm hiểu đến 18h30 thì phải T_T.

Lúc ý mẹ tớ mới đi ra ngoài về. Tớ mới bắt đầu ngồi đọc Chương 4 được 1 tiếng rồi ăn cơm hix.

Về Chương 4 - Tính rating

Về trải nghiệm đọc trên Manning

Chương này thật sự tớ thấy cũng khá là hay khi đọc theo kiểu black-box.

Thật sự thì chỉ cần nhìn phần Mục lục và hình vẽ tớ cũng hiểu qua về 80% ý tác giả định nói rồi @@.

Cuối cùng vẫn là code thôi. Sách thì là tài liệu, đọc tài liệu mà giúp hiểu đoạn code ý là tác giả thành công rồi @@.

Còn giải thích tại sao tác giả lại phải viết dài thế thì tớ cũng không rõ nữa :(.

Cơ mà đọc kiểu này tớ nghĩ đủ thông tin và cũng đủ hiểu code, đủ đạt được output tớ đạt ra rồi.

Khi nào tớ mà không hiểu lắm thì tớ sẽ đọc quyển sách Quang mua trên Manning nhé!!! Thanks Quang!!!

À có thêm 1 ý này nữa là đọc cái gì khó quá, nhìn hình vẽ mà không hiểu ngay thì tốt nhất cứ tạm thời skip :(

Hoặc là kiến thức của mình có vấn đề, hoặc là tác giả viết kiểu gì đó khó hiểu quá.

Tất nhiên là sẽ có cách giải quyết cho cả 2 trường hợp đấy O_O.

Cơ mà tớ thấy quyển sách này tác giả viết và có hình vẽ công nhận dễ hiểu thật vì không cần đọc cũng đã biết tác giả định nói gì thông qua hình vẽ rùi.

Về nội dung chương 4

Okay lan man quá quay lại chương 4 nào.

Đầu tiên là nhắc lại có 2 kiẻu rating là

Tớ cũng đã giải thích ở bài viết trước rùi @@.

Chương này tác giả tập trung nói về implicit rating.

Vậy thì explicit rating để làm gì và có dùng không.

Thật sự thì explicit rating thì vẫn sử dụng.

Từ implicit rating tác giả sẽ có 1 công thức để tính ra explicit rating.

Từ rating đấy tác giả sẽ dùng để làm input cho Recommender System.

Đây chính là các bước trong RS

Figure 4.1. Data processing model for recommender systems

Chương 4 này là đang ở bước thứ 2, preprocessing.

Vậy thì công thức để tính rating cuối cùng từ implicit rating là gì?

Đầu tiên thì cần nói implicit rating gồm những input là gì dựa vào Table 4.4. Weights on events[a] (view table figure)

Ngoài ra thì còn có các yếu tố sau nữa

Đấy thì dựa vào 3 cái đấy để tính ra là rating cuối cùng là thế nào.

Tùy theo trang web, tùy theo người nghĩ ra thuật toán, tùy theo paper nghiên cứu trên mạng mà họ chọn cái gì.

Tớ thấy yếu tố IFF có vẻ không phù hợp với tớ vì là thực sự tớ cũng chỉ thích những item nào nhiều người mua thôi vì những item mới mà ít người mua, ít sao sợ là hàng giả lắm hix. Có lẽ vì tớ hơi bị đi theo đám đông hix.

Về nội dung Chương 4 tớ chưa đọc

Ngoài ra còn 1 chương này nữa tớ cũng chưa đọc kỹ (tớ vẫn chưa dùng 5-minute free hôm nay, chắc tớ cần unlock vì đoạn phân tích này chắc cũng khá hay hix).

4.4.2. Considerations of calculating ratings Binary user-item matrix Time-based approach Hacker News’s algorithm Behavior-based approach

Thật sự nếu bỏ qua cái này thì cũng không làm sao cả nhưng mà mình sẽ bị mất mất cái gốc @@.

Kiểu như cứ tập trung chăm chăm chạy code mà không biết code ý tại sao mà có hix.

Vậy thì cứ nhìn theo code đấy mà làm theo là 1 hướng không đúng lắm.

Vì thực ra là tác giả đưa ra các công thức tính rating như trên dựa vào những công thức đã có và dựa vào quan sát tác giả hix.

Có lẽ mỗi trang web có 1 cách tính rating từ implicit rating khác nhau!!!

Về đoạn code chưa công thức tính rating

https://github.com/9health/moviegeek/blob/master/builder/implicit_ratings_calculator.py

Đây là đoạn mà tính ra rating cuối cùng từ implicit rating.

Cách chạy thì làm như thế này

python populate_logs.py

python –m builder.implicit_ratings_calculator

python manager.py runserver 8001

Về bước thứ nhất thì tớ đã chạy luôn từ chương 3 và có rồi.

Ở bài viết hôm trước tớ quên mất nói với Quang là tớ thấy cái database đấy nhìn trông kiểu synthetic (tổng hợp, giả) quá nên là tớ copy cái database mà từ folder mà Quang copy sang hôm trước (may quá, có Quang copy, cảm ơn Quang hix).

Vậy là tớ hiện tại đang dùng 2 database

Nói chung để làm tiếp theo quyển sách thì tớ sẽ trỏ cái vào db_populate.sqlite3

Còn sau khi làm xong tớ sẽ quay lại db.sqlite3 gốc mà chưa bị kiểu tạo dummy user =.=

Tớ thì chưa chạy script này đâu.

Trước khi chạy với sau khi chạy tớ sẽ chụp ảnh lại user 400005 xem như thế nào T_T.

Tớ nghĩ là có nhiều thứ sẽ bị thay đổi :-?

Ngoài ra nếu Quang xem đoạn code implicit_ratings_calculator.py trong folder builder sẽ thấy đấy kiểu như là 1 chương trình riêng chả liên quan gì đến cái mình start webserver luôn :-?

Cũng có các hàm def riêng, các hàm main riêng và hàm để gọi hàm main nữa!!!

Ban đầu tớ đọc Chương 4 còn nghĩ tác giả viết nhầm vì thấy cái chỗ hướng dẫn nhìn quen quá.

Mà hóa ra hôm trước mình nóng vội quá đang đọc Chương 3 mà chạy luôn Chương 4 trong khi không hiểu gì thì phải =.=

Hình như tớ quên mất chạy dòng code thứ 2 chạy builder.implicit_ratings_calculator rồi =.=

Thôi để kiểm tra lại sau vậy.

Cảm ơn tác giả đã tổ chức code rất gọn gàng hix. Muốn thêm gì thì thêm, file hay folder gì. Tớ thấy rất là neat!!!

Cảm ơn Quang giới thiệu quyển sách này.

Một vài lời khác

Thanks Quang đã đọc đến đây và sorry tớ viết muộn quá :(.

Đến giờ đi ngủ rồi.

Bài viết trước tớ có nhắc đến mật khẩu thì tớ mới nhớ ra mật khẩu lần 2 của tớ ở công ty cũ là CQNzBBxAv80r. Công ty cũ bắt mật khẩu mặc định tăng lên 12 ký tự hix.

Để đảm bảo tớ nhớ trong não thì tớ có thể viết lại y hệt cho Quang lúc gặp Quang, chỉ cần nhớ ký tự đầu thôi ^_^

Còn về Azure subscription thì tớ đọc kỹ lại slide họ gửi rồi Quang ạ!!!

Bắt buộc mình phải đăng ký Azure offer đấy bằng account subdomain.onmicrosoft.com Quang à!!!

Thôi thì mình cứ đăng ký trước vậy. Sau này giả sử không dùng M365 nữa vì đắt quá thì chỉ để lại 1 account để duy trì cũng okay Quang à!!! Chắc chỉ cần dùng bản Business Basic $6/user/month để quản lý Azure là okay.

https://www.microsoft.com/en-us/microsoft-365/business/compare-all-microsoft-365-business-products

Còn nếu mà 1 năm sau xin được tiền của nhà đầu tư hay self-funding mà cảm thấy M365 okay thì tiếp tục hix. Mà chát phết T_T. Nhưng mà mình sử dụng được hết tài nguyên thì sẽ thấy quý giá T_T.

Còn cách optimize cost nhất là ra ngoài lại dùng Outlook và Teams như bình thường thôi sau khi hết 1 năm cho các account khác T_T.

Tớ cũng hơi suy nghĩ tiêu cực ở bài viết trước nhưng mà viết ra xong hết thì lại xong rồi hix. Cũng thấy thoải mái hơn rồi.

Cứ cố gắng dần thôi, hi vọng mọi thứ sẽ okay.

Tớ cũng cảm giác có lẽ mình cũng đang đúng hướng dần dần, mặc dù vạch đích ở rất xa nhưng mình cứ đi có lẽ sẽ đến hix.

Cảm ơn Quang đã mua quyển sách kia và giúp tớ tạo database model cho food nhé. Có gì khó khăn cứ commit, tạo issue và tag tớ vào nhé nếu khó quá!!!

Cảm ơn Quang nhiều!!!

9health commented 1 year ago

Hello @quangvv9Life,

Tình hình là qua tớ cũng đã tìm cách recover được 2 tiếng mà không dậy sớm buổi sáng được hic.

Hôm nay đám chuột đi đâu rồi và nói chung cũng ngủ được =.=

Cơ mà ngồi làm clip với mama tới hơn 12 giờ sáng =.=

Về thời gian biểu của tớ hôm qua

Ăn sáng xong là 9h hơn, tớ ngồi vào bàn, sửa sửa 1 ít tài liệu liên quan tới Azure offer rồi share cho Quang trên OneDrive rồi đấy.

Tiếp xong tớ ngồi update file Future rồi file Ghi Nhận Cảm Xúc cho Thứ 7 tới Thứ 3.

Mẹ tớ thì hôm qua đi tập hát xong còn đi với cô nào đấy tới 1h trưa mới về ăn cơm =.=

2h kém ăn xong thì ngủ tới 3h15 chiều.

Tớ ngồi update tiếp file trên =.=

5h30 thì nói chung cũng hòm hòm và tớ cũng gửi email rồi.

Tuần này chị kia ốm nên khả năng tớ không gặp được hic.

Còn tối nay mẹ tớ về quê nên khả năng có khi mai tớ qua chỗ Quang được buổi chiều như hôm trước hic.

Quang đã khỏi đau họng chưa :|

Về đọc tiếp Chương 4 - Ratings

Thanks Quang đã mua eBook trên Manning nhé.

Tác giả trong Chương 4 cũng bảo là thích mua sách trên Manning với O'Reilly vì là ở đấy rẻ hơn 1/2 so với Amazon =.= và cung cấp nhiều thứ free hơn :|.

Mà tớ thấy đúng thế thật.

Đọc trên Manning liveBook có nhiều tracker quá =.= Tớ có đo xem CPU tiêu thụ như thế nào thì đọc trên liveBook gấp 12 lần vào trang GitHub =.= Ngoài ra thì họ còn scramble text, load 1 đống JavaScript bảo sao chả tốn CPU hơn T_T.

Ví dụ nếu ở trang Manning liveBook cả ngày pin chỉ có 10 tiếng thôi nhưng nếu ở trang GitHub cả ngày pin được 20 tiếng như máy tớ...

Về hệ thống Recommend ở các trang

Cái này thì tớ chưa nói ở bài viết trước nhưng mà đọc xong tớ có thấy hóa ra là

Quang thì chắc chưa dùng Amazon mấy vì ở VN không có nhưng ở Nhật thì Amazon nói chung là 1 trang web e-commerce cũng thuộc loại to đùng luôn. Có cả Rakuten cạnh tranh nữa cơ mà nói chung tớ mua đồ thì thích vào Amazon hơn =.=

Tớ mua thì thường là cho em tớ chứ cũng không mua cho tớ nhiều hix. Đồ tớ mua cho tớ ít lắm. Khi nào bắt buộc phải mua như là giầy đi lâu quá bị hỏng, trời mưa tầm tã 1 tuần mà không có giầy đến công ty nên order và cuối tuần ngồi ở nhà nhận =.=

Thực ra ở siêu thị AEON gần ga tớ hay đi chợ cũng có bán giầy cơ mà có lẽ là do không biết tiếng nên cũng sợ không dám mua =.= Mua trên Amazon cũng chọn giầy rẻ nhất mà mua thôi, hình như của hãng Dunlop gì ý. Sau cái giầy ý có vấn đề gì đó tớ đi nhiều bị chai chân ở ngón bên phải.

Hix thôi tớ lan man nhiều quá =.=

Túm lại tớ cứ nghĩ là Amazon recommend theo kiểu non-personalized cơ vì nghĩ cứ cái gì tốt, được explicit rating cao là họ sẽ giới thiệu.

Cơ mà thực sự họ dựa và lịch sử order của mình và khẩu vị của những người như mình (user's taste) trong cùng 1 category đấy để đưa ra recommendation hay suggestion =.=

Quả thật là chạy hệ thống đấy ngốn CPU và RAM thật vì nhân ma trận, tính toán nhiều :|.

Về trang NYTimes thì khi vào sẽ thấy có 3 cột ở bên phải là

Thực sự thì hồi xưa tớ cũng hiểu Most Emailed với Most Viewed là gì thôi =.=

Giờ tớ mới hiểu cái Recommended for You là dựa trên những articles mình đọc =.=

Người Mỹ kể cũng lạ thật vì có Most Emailed vì nói thật ở mấy trang tin lớn ở Việt Nam chả có link đấy luôn =.=

Most Emailed và Most Viewed là non-personalized recommendations.

Cứ cái nào sắp xếp dựa vào máy và không liên quan tới lịch sử đọc sách của người dùng thì sẽ là non-personalized hết.

Về 5 phút free trên trang Manning liveBook

Tớ có dùng unlock free 5 phút mỗi ngày ở trang liveText và thú thật là 5 phút đấy đủ để tớ copy hết Chương 4 ra 1 file text như Quang có thể vào folder 10_RS > Knowledge > Text được share trên OneDrive ý.

Tớ cũng đo thử là xem tác giả viết bao nhiêu từ ở Chương 4 thì là 7K từ. Vậy là nếu mà viết dễ hiểu thì đọc trong 30 - 45 phút là xong (tốc độ 250 wpm) =.= Tớ cũng thử đọc hết và thấy đọc được hết trong khoảng thời gian như thế thật.

Tớ cũng khá là bất ngờ vì Manning cho mình copy text ra từ website.

Như các trang web bình thường mà hỗ trợ đọc eBook online chắc là họ sẽ dùng JavaScript để chặn không cho copy hết =.=

Câu hỏi đặt ra là tại sao Manning lại làm như thế, cho mọi người copy text free?

Nhỡ mọi người copy cả quyển sách thì sao?

Nói thật tớ nghĩ cho copy chả ảnh hưởng gì cả =.=

Copy text về thì còn 1 công đoạn nữa là format hay thuật ngữ chuyên ngành là typesetting.

Nếu muốn chuyển cái ý về giống như nguyên bản, chỗ nào Header 1, Header 2 các thứ, chỗ nào in nghiêng, chỗ nào code thì chắc mất cả tháng mới format xong cả quyển =.=

Vậy nên cho copy text thoải mái cũng không lo lắng gì cả vì reproduce ra 1 quyển eBook như thế khá tốn công (xưa tớ cũng làm eBook prc, eBook PDF nên tớ biết...)

Tớ đánh giá Manning tốt ở điểm cho copy text như thế =.=

Gọi là 5 phút thôi chứ tớ thấy phải được 10 hay 15 phút.

Tớ mất đâu độ chục cái Ctrl + C va Ctrl + V là copy hết Chương 4 ra TextEdit rồi =.=

Hình vẽ có sẵn và không bị locked rồi.

Vậy là đọc thôi...

Bravo Manning!!!

Thanks Quang đã tìm ra quyển sách đấy!!!

Nói thêm 1 chút về Implicit Ratings

Đọc trong này tớ thấy lặp lại những gì mà Quang nói cho tớ hồi xưa là user họ bảo họ thích nhưng mà thực sự họ có thích không???

Tác giả cũng ví dụ là tác giả xem 1 bộ phim đấy vì nghe bảo nó rất chán @@.

Có lẽ kể những chuyện như là bộ phim ý rất tệ với bạn bè thì có lẽ là bạn bè sẽ thích hơn @@.

Có những người lại có những suy nghĩ như thế mới kỳ lạ =.=

Mà đúng là có khi như thế thật =.=

Phim đoạt giải Oscars có phải ai xem cũng hiểu đâu =.= Phim mà kiểu action, kiểu đầu tư nhiều, quảng cáo nhiều như Avengers, doanh thu lên cả tỷ đô thì lại nhiều người xem cơ mà rating thấp =.=

Phim Oscars thường rating sẽ cao hơn =.=

Như ở trang IMDB thì Top 250 phim hay nhất người ta dựa và rating của user (tất nhiên tớ nghĩ không phải user nào cũng có rating weight như nhau =.= chắc user mà kiểu profile khủng, hiểu thật sự về phim sẽ có trọng số cao hơn =.=).

Top 250 đấy không dựa vào revenue của phim đấy để sắp xếp (sort) =.=

Tại sao thì như thế tớ cũng không biết =.=

Có lẽ khi xem 1 bộ phim người ta không đặt nặng vấn đề tài chính, doanh thu hay nói nôm là tiền bạc mà người ta đặt nặng cái đánh giá vào nội dung của phim =.=

1 câu hỏi đơn giản là "Phim có hay không?" sẽ được trả lời trên trang IMDB theo phương pháp định lượng.

Ý là những bộ phim mà có chi phí thấp nhưng doanh thu cao vì nội dung hay tất nhiên vẫn lọt vào Top rồi =.=

Hơi lan man 1 xíu thì làm sao để tránh những thứ như Quang nói hay tác giả có đề cập là user có thực sự thích item này khi rating 5 sao không???

Cái đấy cần dựa vào behavior của user trên website như thế nào.

User đấy click vào những chỗ nào, nút nào cũng là 1 thông tin quan trọng biết được user đấy có thật sự thích item đó hay không.

Mở rộng ra về implicit và explicit

Tớ bắt đầu suy nghĩ thêm về 2 khái niệm này vì nói thật trước nghe Quang nói mà tớ cũng chỉ nghe thôi chứ cũng không thực sự hiểu ý của Quang là gì. User like có thật là like không =.=

Quang cũng không giải thích rõ được thêm thành ra là cái đấy cũng vẫn lưu vào đầu tớ nhưng mà xong thì cũng chả có gì thêm hic =.=

Đọc tới chương này và dành thời gian ngẫm nghĩ mới bắt đầu phân tích được nhận xét của Quang vậy =.=

Thật sự thì cái này cũng giống như là tâm lý học mà trước 1 bạn tớ có kể cho tớ.

Ví dụ như khi mình kiểu phản ứng với 1 người khác không phải qua lời nói mà qua cử chỉ chẳng hạn như là tay nắm chặt, mặt đỏ gay chẳng hạn.

1 ví dụ khác là

Khi một người vào 1 cửa hàng và cứ nhìn món hàng đấy chăm chú nhưng mà không mua chẳng hạn.

Vậy thì người bán hàng nếu mà tinh ý sẽ có hành động như thế nào @@.

Nếu mà họ đến chơi thôi và nhìn 1 lần thì có lẽ là họ sẽ không quay lại.

Nhưng mà nếu họ chăm chú nhìn và nếu họ quay lại lần sau nữa thì người bán hàng nên có hành động gì không?

Có nên giảm giá để bán được hàng không?

Cái này có lẽ là tớ đã gặp ở Nhật rồi =.=

Có 1 lần kính của tớ bị hỏng do là tớ kiểu gập mạnh tay quá.

Tớ cũng cần thay kính mới nhưng mà tiếc xiền vì tận gọng kính giá toàn hơn $100 :(.

Thế là tớ đến 1 cửa hàng kính cách nhà khoảng 20 phút đi bộ xem nhưng mà không dám mua.

Cửa hàng bán kính đấy thì cũng ít khách lắm T_T.

Cơ mà vì rảnh và lúc đó cũng cần phải có gọng kính mới để làm 1 số việc khác nên khi tớ quay lại lần 2 thì thấy cái gọng kính giá rẻ nhất giảm xuống $70 rồi.

Vậy là tớ thay luôn gọng mới hix.

Ở Nhật họ không chịu thay mắt kính cho gọng kính ở nước ngoài nên phải mua cả gọng, cả mắt mới haizzz.

Đấy thì người bán hàng họ biết giá kiểu bán lẻ và họ có thể discount được để sao cho người muốn mua sẽ mua =.=

Cái này có lẽ liên quan nhiều tới tâm lý nhỉ hix.

Mà tớ lại không giỏi cái đấy lắm.

Recommendation này cũng dựa trên chủ yếu là tâm lý hix.

Có lẽ Quang giỏi cái này hơn tớ, cảm nhận giỏi hơn tớ thì sẽ hiểu user hơn tớ =.=

Chứ tớ nói thật đi làm tớ toàn làm theo kiểu implicit thôi Quang à. Sếp của tớ cứ bảo em phải thể hiện ra ngoài đi cơ mà tớ kệ. Miễn sao mình được giao việc và hoàn thành theo cách của mình, xong thì báo cáo =.= Còn explicit thì tớ kệ.

Hay là tớ về quê chẳng hạn :( Mẹ tớ bắt tớ lau nhà cho dì. Tớ thấy dì tớ giặt thảm, giặt dép, giặt chiếu mặc dù nói thật mình cũng không muốn làm đâu nhưng mà tớ thấy phụ nữ làm thế thành ra cũng muốn giúp hix. Cái đấy gọi là implicit hay explicit nhỉ.

Nếu mà thực sự mình nói ra mình muốn giúp có lẽ là explicit nhỉ.

Còn nếu mà mình cứ âm thầm làm, âm thầm giúp mà chả nói gì có lẽ là implicit nhỉ.

Chính vì sự mù mờ đó mà nhiều người lầm tưởng tớ thật sự muốn giúp nhưng mà tớ kiểu thể hiện ở mức implicit cũng không đúng nữa @@. Có lẽ thế =.=

Hoặc ví dụ như mẹ tớ bảo tớ làm video chẳng hạn =.= Thực sự tớ có khả năng tớ cứ giúp thôi nhưng mà đấy gọi là implicit của mình hay không tớ không biết nữa.

Có lẽ cái feeling của tớ nó ở sâu lắm mà cả implicit hay explicit cũng khó thể hiện ra ngoài.

Thành ra là dễ gây hiểu nhầm cho những người kiểu hơi non nớt hix.

Mà có khi tớ còn hiểu nhầm cả implicit của mình nữa cơ. Hiểu nhầm explicit của mình là đương nhiên rồi. Haizzzz.

Sorry TextEdit, GitHub, Quang vì đã để tớ viết ra mấy cái kiểu trút bỏ cảm xúc thế này =.=

Một ít trường hợp khác về recommendation

Tiếp theo chuyện tác giả chỉ thích xem những bộ phim mà có rating thấp (ở đây là explicit theo tớ nghĩ thế) chẳng hạn vì 1 lý do gì đó.

Vậy thì recommend cho user như là tác giả có nên recommend những bộ phim có rating cao không?

Hay là nên tìm 1 user nào có khẩu vị (user's taste) giống như là tác giả và recommend 1 list y thế?

Hay là recommend những bộ phim rating low cùng category như thế?

Đây là những kỹ thuật tâm lý mà cần quan sát từ ngoài đời và áp dụng vào phần xử lý phía sau của 1 website hix.

Lại tâm lý :(. Cái này thì trẻ con cũng biết mà không hiểu sao tớ lại không biết nhỉ =.=

Về đoạn code tính implicit rating

https://github.com/9health/moviegeek/blob/master/builder/implicit_ratings_calculator.py

def calculate_implicit_ratings_for_user(user_id):

    data = query_aggregated_log_data_for_user(user_id)

    agg_data = dict()
    max_rating = 0

    for row in data:
        content_id = str(row['content_id'])
        if content_id not in agg_data .keys():
            agg_data[content_id] = defaultdict(int)

        agg_data[content_id][row['event']] = row['count']

    ratings = dict()
    for k, v in agg_data .items():

        rating = w1 * v['buy'] + w2 * v['details'] + w3 * v['moredetails']
        max_rating = max(max_rating, rating)

        ratings[k] = rating

    for content_id in ratings.keys():
        ratings[content_id] = 10 * ratings[content_id] / max_rating

    return ratings

Đọc Chương 4 thì cũng thấy công thức toán học dùng tính implicit rating thế nào rồi.

Khi chuyển thành code, chuyển thành ma trận các thứ mới thấy tác giả implement tốt thật =.=

Tớ nói thật là xưa tớ thấy tớ khá là kém về đoạn chuyển từ thuật toán ra code.

Tớ cũng không hiểu tại sao nữa =.=

Thuật toán người ta viết rõ như thế rồi, chỉ cần hiểu là chuyển ra code được mà tớ cứ bị struggle cái phần đấy =.=

Cơ mà sau này thì cũng dỡ hơn rồi vì tớ toàn kiểu đi sửa code, đi maintain ý thành ra cũng biết 1 vài pattern hay dùng chẳng hạn.

Chứ tớ mà nghĩ về thuật toán là đầu tớ như vào 1 cái loop và ở mãi trong ý luôn haizzz.

Như đoạn code trên tác giả có 3 phần chính ở 3 vòng for

Cách chạy thì là

python3 -m builder.implicit_ratings_calculator.py

Chạy rất là đơn giản =.=

Đây là trang user 400005 trước khi chạy đoạn code này

Screenshot 2022-12-27 at 21-23-20 MovieGEEKs

Đây là trang user 400005 sau khi chạy đoạn code này

Screenshot 2022-12-27 at 21-29-54 MovieGEEKs

Screenshot 2022-12-27 at 21-23-38 MovieGEEKs

Nói thêm 1 chút về đoạn code trên từ góc nhìn hardware design

Nói thật là đoạn code trên mà implement bằng hardware chắc là mất 2 tuần tới 1 tháng để cả design và cả verify đấy haizzz.

Lâu rồi tớ chưa làm nữa nên estimate chắc có khi cũng sai =.=

Cơ mà làm hardware thì code không chỉ như trên đâu mà phải căn ke từng bit cho phép nhân với phép cộng =.=

Ví dụ như ở bên C# có 8-bit, 16-bit, 32-bit, 64-bit chứ ở bên bọn tớ bit gì cũng có 7-bit có, 33-bit có, lạ đời lắm =.=

Rồi data vào như thế nào, ra như thế nào nữa, hoạt động với tần số bao nhiêu, throughput là bao nhiêu =.=

Xuống hardware là cả 1 mớ lằng nhằng luôn.

Cơ mà code C hay code Python hay code software chỉ cần thế này là đủ rồi...

Nhận xét thêm về cách tác giả code

Thật sự nhìn cách tác giả xây dựng database, cách lấy dữ liệu từ database ra, cách xử lý dữ liệu đầu ra như thế nào tớ thấy Python viết simple thật và làm prototype nhanh thật.

Chỉ cần tìm đúng sách, đúng ví dụ là áp dụng được chứ cái .NET kia nào là LINQ, nào là cái gì gì đó mà chưa mường tượng được ra mình sẽ làm thế nào.

Chứ chỉ cần nhìn cách tác giả code, cách tác giả tổ chức files, folders là mình có thể làm được 1 project kha khá to rồi đấy.

Và nhiều người cùng join làm project đấy, integrate mà không có vấn đề gì cả...

Cái này tớ thấy dễ hiểu hơn là Taiga nữa (có lẽ Taiga không có document viết chi tiết đi kèm nên khó hiểu hix).

Và có khi đọc xong quyển này rồi thì tự dưng đọc code Taiga lại thấy dễ hơn =.=

Okay nói thêm 1 chút lấy dữ liệu ra từ database nữa.

Đây là đoạn code của tác giả dùng

def query_aggregated_log_data_for_user(userid):

    user_data = Log.objects.filter(user_id = userid).values('user_id',
                                                            'content_id',
                                                            'event').annotate(count=Count('created'))
    return user_data

Trong sách thì là lệnh SQL dài ngoằng thế này

Listing 4.1. SQL script to retrieve ratings for a user

SELECT
    user_id,
    content_id,
    mov.title,
    count(case when event = 'buy' then 1 end) as buys,                  1
    count(case when event = 'details' then 1 end) as details,           2
    count(case when event = 'moredetails' then 1 end) as moredetails    3
FROM   evidenceCollector_log log
JOIN   movies mov                                                       4 5
ON     log.content_id = mov.id                                          6
WHERE  user_id = '4005'
group by user_id, content_id, mov.title                                 7
order by buys desc, details desc, moredetails desc                      8

Tại sao lại có sự khác nhau như thế =.=

Do đoạn code trên ở Python là đã model lại database theo kiểu ORM và Python có lẽ cũng có 1 kiểu LINQ nào đấy giống như là bên .NET

id          created                     content_id  event       session_id                            user_id    
----------  --------------------------  ----------  ----------  ------------------------------------  -----------
1           2022-12-14 11:37:29.805451  10121392    details     ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
2           2022-12-14 11:37:31.753527  10121392    more_detai  ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
3           2022-12-14 11:37:31.756146  10121392    details     ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
4           2022-12-14 11:40:38.408286  5618690     details     ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
5           2022-12-14 11:44:13.825325  5537002     details     ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
6           2022-12-14 11:44:15.677044  5537002     more_detai  ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
7           2022-12-14 11:44:15.681723  5537002     details     ac631f04-7ba3-11ed-afd2-000d3a5a3fa5  14271057339
8           2022-12-14 12:12:19.562973  10152736    details     87524f50-7ba8-11ed-afd2-000d3a5a3fa5  33606199645
9           2022-12-14 12:29:42.083685  10380900    details     87524f50-7ba8-11ed-afd2-000d3a5a3fa5  33606199645
10          2022-12-14 12:29:45.168987  10380900    more_detai  87524f50-7ba8-11ed-afd2-000d3a5a3fa5  33606199645

Xem lại 1 chút database trông như thế nào cho dễ hiểu lệnh trên hơn!!!

Thực ra dùng ORM rồi thì cũng chả cần chui vào database xem kỹ làm gì cho mệt đầu =.=

Cứ hiểu theo kiểu object, class là okay rùi.

À đoạn code Python có 3 vòng for ở trên ý tớ cứ nghĩ tớ giỏi rồi nên lao đầu vào đọc luôn cơ mà đến cái đoạn tính max tớ vẫn chưa hiểu gì =.=

Mất 20 phút ở chỗ đấy và nghĩ mãi.

Cuối cùng quay lại đọc phần giải thích trong sách thì mới hiểu ra. Mặc dù biết là normalize rồi nhưng chưa hiểu normalize là như thế nào hay implement như thế nào =.=

Haizzz, tác giả thật tốt khi share code và sách ;(.

Thêm 1 cái nữa khi tớ chạy đoạn code tính implicit rating thì tớ quên mất không copy database trước khi chạy rồi haizzz. Thôi dùng đoạn database tính lại rồi vậy...

Về kiểm tra kết quả tính implicit rating

Một cái nữa sau khi tớ chạy và xem kết quả ở trang

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/user/400005

Thì tớ thấy rating tính theo kiểu implicit hiện ra rồi.

Cơ mà có 1 cái là phần tính similarity với các user khác.

Ở bài viết trước tớ quên nói với Quang là phần getting similarity tính toán rất là lâu luôn. Cần 6s để có kết quả ấy!!!

Tớ cũng chưa check thử CPU lúc ý lên thế nào nữa... Cái này tớ sẽ tạo 1 issue riêng hix.

Ngoài ra thì tớ thấy Quang có chạy Python server từ hôm nào ấy mà giờ tớ vào trang web trên là cái máy ảo của tớ trên Azure đơ luôn Quang à, không login được nữa trong vòng 5 phút :(

Nếu mà tớ thử lại với user 3 với database chưa populate thì mọi thứ lại bình thường

http://ninehealth.westus.cloudapp.azure.com:8080/analytics/user/3/

Có lẽ tớ sẽ tạo 1 issue khác và viết sau!!!

Cơ mà thôi tớ điều tra luôn =.=

Có lẽ do ma trận của user 400005 tạo ra tính toán similarity to quá Quang à!!!

sqlite> SELECT * FROM collector_log WHERE user_id=400005 ORDER BY id DESC LIMIT 10;

id          created              content_id  event       session_id  user_id   
----------  -------------------  ----------  ----------  ----------  ----------
100127      2022-12-24 01:16:03  2582782     details     442692      400005    
100125      2022-12-24 01:16:03  2140479     details     442692      400005    
100124      2022-12-24 01:16:03  4172430     details     442692      400005    
100112      2022-12-24 01:16:03  1878870     details     442692      400005    
100110      2022-12-24 01:16:02  3553976     moreDetail  442691      400005    
100106      2022-12-24 01:16:02  4975722     moreDetail  442691      400005    
100105      2022-12-24 01:16:02  2005151     details     442691      400005    
100094      2022-12-24 01:16:02  4052882     moreDetail  442691      400005    
100092      2022-12-24 01:16:02  3640424     details     442691      400005    
100088      2022-12-24 01:16:02  4513674     addToList   442691      400005    
sqlite> SELECT COUNT(*) FROM collector_log WHERE user_id=400005;

COUNT(*)  
----------
16606     
sqlite> SELECT COUNT(*) FROM collector_log WHERE user_id=3;

COUNT(*)  
----------
0         

Có vẻ tớ lấy data chưa đúng lắm. Dùng bảng analytics_rating đúng hơn

sqlite> SELECT * FROM analytics_rating WHERE user_id=400005 LIMIT 10;

id          user_id     movie_id    rating      rating_timestamp            type      
----------  ----------  ----------  ----------  --------------------------  ----------
921502      400005      0490215     8.98        2022-12-27 14:25:34.400575  implicit  
921503      400005      0803096     0.08        2022-12-27 14:25:34.414608  implicit  
921504      400005      0918940     0.12        2022-12-27 14:25:34.427808  implicit  
921505      400005      1083452     9.43        2022-12-27 14:25:34.442270  implicit  
921506      400005      1179933     8.04        2022-12-27 14:25:34.455514  implicit  
921507      400005      1211837     0.12        2022-12-27 14:25:34.472792  implicit  
921508      400005      1219827     7.71        2022-12-27 14:25:34.487346  implicit  
921509      400005      1289401     0.12        2022-12-27 14:25:34.502661  implicit  
921510      400005      1355644     9.22        2022-12-27 14:25:34.520740  implicit  
921511      400005      1386697     0.04        2022-12-27 14:25:34.534733  implicit  
sqlite> SELECT COUNT(*) FROM analytics_rating WHERE user_id=400005;

COUNT(*)  
----------
71        
sqlite> SELECT COUNT(*) FROM analytics_rating WHERE user_id=3;

COUNT(*)  
----------

21        

Thực sự cũng chưa hiểu lắm tại sao Quang à =.=

Cơ mà tớ nghĩ là có lẽ để cho an toàn chỉ nên chạy 1 Python web server 1 người 1 thời điểm thôi =.=

Tớ nghĩ phần của Quang đang build database model thì tạm thời chưa cần chạy cũng được hic.

Tớ nghĩ chỉ cần dùng command line là đủ ấy T_T.

Quang có thể là vào và tắt hộ tớ cái Python web server ở port 8081 đang chạy được không hic!!!

Cảm ơn Quang nhiều T_T.

Vì tớ mà dùng database populate và vào trang analytics của user 400005 là máy ảo treo luôn.

Thực ra thì tớ cũng có thể cancel cái Quang đang chạy được nhưng mà biết đâu nhỡ Quang đang chạy cái gì mà tớ cancel làm hỏng thì sao =.=

Nên tớ bắt chước các bác Nhật là cứ email cho user mà đang chạy job ý!!!

Thanks Quang nhiều!!!

Về kế hoạch tiếp theo

Tớ nghĩ Chương 4 với tớ như thế hòm hòm rồi.

Tiếp tục tớ sẽ qua đọc Chương 5 O_O.

Sáng nay thì tớ cũng không dậy sớm được hic.

1 tuần có 5 ngày mà 3 ngày cái khoảng 2 giờ bị shift đi rồi hix.

Cũng chả biết làm thế nào nữa, cuộc sống vary mà hix.

Thôi lại tiếp tục cố gắng recover trong ngày vậy.

Tối qua tớ đọc từ 8h15 tới 9h30 trong lúc mẹ tớ đang xem bóng đá.

Tớ ra phơi quần áo xong thì 10h.

Mẹ tớ giục làm clip từ 8h tối thì phải nhưng tớ đang đọc dở cái 2 tiếng nên thôi :( Cũng buồn cho mẹ lắm.

Sau may mà đọc cũng hết 7K chữ rồi nên ra giúp mẹ.

Tới 12h hơn thì làm xong clip và 2 mẹ con đi ngủ T_T

https://www.youtube.com/watch?v=PZkH_u-NPRE&list=PLzc9r8PlgBfdFEUoSmvoFmw1Ar9mQQQSq&index=3

Trong này clip thì tớ vi phạm bản quyền cả nhạc này (bị nhiều lần rồi mà không sao) rồi cả hình ảnh (cắt ghép từ VTV1 ý).

Không hiểu là có bị yêu cầu gỡ xuống và bị xóa không đây haizzz.

Hi vọng là không.

Chiều nay thì 1h tớ giúp mẹ bê loa ra Phường rồi quay phim mẹ hát nữa.

Chắc là 2h hay 3h chiều mới về nhà T_T.

Mẹ tớ định 10h30 sáng ăn mà không làm được. Chắc 11h15 tớ phải ăn trưa rồi và còn ngủ trưa nữa T_T.

Hi vọng ngày hôm nay là 1 ngày tốt lành.

Chúc Quang cũng như thế!!!

_À sáng nay 7 giờ dậy tớ viết file này và giờ mới xong. Lúc 8 giờ kém 15 mẹ gọi ra đánh răng rửa mặt, ăn sáng TT. Cảm giác rất là tồi tệ vì có 2 tiếng mỗi ngày hứa với bạn mà không thực hiện được hic. Giờ thì cũng đỡ rồi hic. Có 1 suy nghĩ của tớ là Quang hay bảo là mẹ không sống với mình được mãi đâu nhưng mà tớ nghĩ là vì như thế nên mẹ tớ còn sống ngày nào thì tớ làm cái gì được mà mẹ tớ happy thì tớ làm :(. Khi nào mà mẹ tớ không muốn tớ làm nữa thì thôi vậy @@. Tớ cũng không biết tương lai sẽ như thế nào nhưng mà thôi những cái sở thích của mình nó được thì tốt mà không được thì thôi, cứ cho mẹ happy đã rồi tính của mình sau. Cả đến lúc mẹ tớ 90 tuổi, tớ 60 tuổi chẳng hạn @@. Chắc là 60 tuổi tớ mới dám lấy vợ mất @@@@@@@._

quangvv9Life commented 1 year ago

Hi Hải, @9health

Thank Hải đã comment tiến độ theo ngày nhé. Tớ đã tắt server django tại port 8081 rồi nhé.

Mai Hải có qua nhà tớ không ? và mấy giờ vậy ? báo tớ trước nhé

Tớ đang thấy luồng trao đổi vừa ở cả github vừa ở cả outlook rồi imess thế này không quy được về một mối khó quá

Để tớ nghĩ xem có cách nào thống nhất luồng trao đổi không nhé. Thank Hải !!!

BR Quang

9health commented 1 year ago

Hello @quangvv9Life,

Thanks Quang đã tắt Python web server để save resource cho tớ nha @@.

Chiều nay thì 3h30 cuối cùng tớ cũng đã quay video xong cho mẹ và về nhà rồi.

Link video tớ sẽ gửi sau. Hôm nay biểu diễn là cho Tổng kết Đảng (Hội nghị Sơ kết Giữa kì) gì đó có cả bác Phó Chủ tịch ở Quận về @@. Đông lắm @@.

Mà tớ cũng quen nhiều vì đi du lịch với hội CCB của mẹ 3-4 lần rồi, mỗi lần tour 2 ngày, có khi 4 ngày =.=

Bài hát Màu Cờ Tôi Yêu ST Phạm Tuyên do CLB Hòa Thanh CCB Phường Kim Mã Quận Ba Đình TPHN biểu diễn - Minh Sua Nguyen Thi

https://www.youtube.com/watch?v=GtGvfAix56E

Mẹ tớ hôm nay lại không về quê nữa vì mưa với rét.

Tớ cũng chưa biết ngày mai thế nào đây =.=

Thứ 7 khả năng tớ cũng không biết có về quê hay không nữa =.=

Nếu mà về quê chắc khả năng không họp với Quang được rồi.

Mà hình như đợt tới là 3 ngày nghỉ lễ liên tục nhỉ, nghỉ cả Thứ 2 nữa hix =.=

Có gi tớ sẽ nhắn lại sau

Chúc Quang năm mới nhiều thành công và luôn tràn đầy niềm vui nhé!!!

Về Chương 5 - Non-personalized Recommendations

Tiếp tục về trải nghiệm đọc trên Manning

Nói thật xưa tớ đọc sách Quang ạ là tớ hay có xu hướng đọc từ đầu tới cuối quyển sách ý ở chỗ có đoạn nào đọc được.

Cơ mà từ khi vào trang Manning này và đọc theo kiểu

Thì tớ phát hiện ra rằng tốc độ đọc của mình tăng lên đáng kể @@.

Không cần đọc hết cả Chương đấy mà hiểu được Chương đấy nói gì rồi.

Còn đi vào chi tiết, hiểu từng dòng code thì hơi mất thời gian.

Tạm thời bỏ qua cũng được =.=

Mục đích của tớ là chạy và xem là output ra thế nào.

Và giờ thì độ khó từng dòng code cũng đang tăng dần =.=

Để được level code như tác giả thì chắc cũng phải code khá nhiều đấy...

Rất là dễ nhìn mà cũng rất là gọn gàng =.=

Cách đặt tên biến cũng rất thông minh =.= Tớ đặt tên biến lung tung lắm haizzzz.

Về nội dung Chương 5

Lúc bắt đầu đọc nói chung tớ cũng khá mệt vì vừa đi mưa về, lại còn phải mở cửa cất loa các thứ nữa =.=

Cơ mà thôi lại hi vọng là cách làm cũ sẽ có hiệu quả và đúng là có thật.

Chương 5 này đã bắt đầu tập trung vào phần recommendation rồi.

Về recommendation những item phổ biến nhất

Và cái recommendation cơ bản nhất sẽ là hiện thị ra có bao nhiêu người mua (buy) ở ô bên phải (tác giả gọi là chart, tớ thấy chart phải có tọa độ các thứ, tớ thấy cái này giống với cả list hơn =.=).

Thôi tớ nói luôn vào API cho dễ hiểu nhé @@.

http://ninehealth.westus.cloudapp.azure.com:8080

Khi mà mình vào trang Home page của MovieGEEKs thì sẽ có API call như ở dưới

http://ninehealth.westus.cloudapp.azure.com:8080/rec/chart

Data trả về là

{
    "data": [
        {
            "movie_id": "10295212",
            "title": "Shershaah "
        },
        {
            "movie_id": "0993840",
            "title": "Army of the Dead "
        },
        {
            "movie_id": "10329614",
            "title": "Censor "
        },
        {
            "movie_id": "13863968",
            "title": "The Wisdom of Trauma "
        },
        {
            "movie_id": "3110958",
            "title": "Now You See Me 2 "
        },
        {
            "movie_id": "3480822",
            "title": "Black Widow "
        },
        {
            "movie_id": "4876134",
            "title": "The Misfits "
        }
    ]
}

Có vài API này cũng đang được gọi nhưng mà chắc phải đọc các chương sau mới biết được thế nào. Thôi cứ từ từ vậy @@.

http://ninehealth.westus.cloudapp.azure.com:8080/rec/ar/64585374250/

{
    "data": []
}

http://ninehealth.westus.cloudapp.azure.com:8080/rec/cf/user/64585374250/

{
    "user_id": "64585374250",
    "data": {}
}

http://ninehealth.westus.cloudapp.azure.com:8080/rec/cb/user/64585374250/

{
    "user_id": "64585374250",
    "data": {}
}

Có vẻ như là đều gọi đến các kiểu recommendation khác nhau hết =.=

Tiếp theo là kiểm tra xem API đấy xử lý như thế nào

Đầu tiên mình tìm trong Recommender app URL sẽ là thế nào thui

https://github.com/9health/moviegeek/blob/master/recommender/urls.py

urlpatterns = [
    url(r'^chart/', views.chart, name='chart'),

Tiếp đó là xem nội dung hàm chart trong views như thế nào

https://github.com/9health/moviegeek/blob/master/recommender/views.py

def chart(request, take=10):
    sorted_items = PopularityBasedRecs().recommend_items_from_log(take)
    ids = [i['content_id'] for i in sorted_items]

    ms = {m['movie_id']: m['title'] for m in
          Movie.objects.filter(movie_id__in=ids).values('title', 'movie_id')}

    if len(ms) > 0:
        sorted_items = [{'movie_id': i['content_id'],
                          'title': ms[i['content_id']]} for i in sorted_items]
    else:
        print("No data for chart found. This can either be because of missing data, or missing movie data")
        sorted_items = []
    data = {
        'data': sorted_items
    }

    return JsonResponse(data, safe=False)

Điểm chú ý trong này sẽ là object PopularityBasedRecs và hàm recommend_items_from_log

Ấn vào đấy trên GitHub thì ra luôn file chứa hàm đấy là

https://github.com/9health/moviegeek/blob/master/recs/popularity_recommender.py

class PopularityBasedRecs(base_recommender):

    def predict_score(self, user_id, item_id):
        avg_rating = Rating.objects.filter(~Q(user_id=user_id) &
                                           Q(movie_id=item_id)).values('movie_id').aggregate(Avg('rating'))
        return avg_rating['rating__avg']

    @staticmethod
    def recommend_items_from_log(num=6):
        items = Log.objects.values('content_id')
        items = items.filter(event='buy').annotate(Count('user_id'))

        sorted_items = sorted(items, key=lambda item: -float(item['user_id__count']))

        return sorted_items[:num]

Đây lại là 1 folder khác rồi!!! Trước là recommender app.

Còn đây kiểu các hàm recommendations khác nhau viết tắt là recs.

Lại 1 cách tổ chức kiểu khác cũng khá hay ho :-?

Thực sự cho hết vào folder recommender cũng được nhưng mà có lẽ sẽ làm folder ý phình to ra và không đúng với Coding Style của Python, có lẽ thế ý Quang @@.

recs
├── base_recommender.py
├── bpr_recommender.py
├── content_based_recommender.py
├── funksvd_recommender.py
├── fwls_recommender.py
├── neighborhood_based_recommender.py
└── popularity_recommender.py

Quang có thể thấy trong folder recs này có rất nhiều recommendation khác nhau luôn =.=

Tha hồ mà thử nhiều kiểu hự.

Vậy là hiểu sơ sơ về recommendation kiểu Top item như thế là okay rùi.

Nhưng mà có 1 cái trong hình vẽ database của MovieGEEKs app Figure 5.7. MovieGEEKs architecture with the recommender system highlighted có những thành phần là

Như mình thấy kiểu recommendation theo độ phổ biến ở trên thực ra lấy dữ liệu từ Collector app là chính.

Vậy thì Recs database là gì, Recommendation Builder là gì.

Tìm hiểu thêm thì trong Recommender app có file models.py ở đây

https://github.com/9health/moviegeek/blob/master/recommender/models.py

class MovieDescriptions(models.Model):

class LdaSimilarity(models.Model):

class Similarity(models.Model):

class SeededRecs(models.Model):

class Recs(models.Model):

Rất là nhiều model luôn, tớ chỉ copy tên model ra đây thui.

Okay vậy tìm hiểu tiếp nào

Về cách dùng association để recommend

Đây là 1 cách khác để đưa ra item recommend.

Tác giả đưa ra ví dụ là

Đại ý là recommendation ở đây dựa vào association.

Như hồi học tiểu học có biết là tính chất hoán vị (associative) là

a * (b * c) = (a * b) * c

* ở đây là phép nhân, multiply

Association còn có nghĩa là relationship nữa =.=

Tớ cũng chỉ nghĩ đến đây thôi, tìm được đoạn code của tác giả từ ở file này rùi

https://github.com/9health/moviegeek/blob/master/recommender/views.py#L21-L67

Cơ mà đọc cũng chưa hiểu lắm =.=

Code ảo diệu quá.

Thôi từ từ để ngấm dần vậy. Còn không lại dùng đến sách hix.

Về một vài nội dung khác

Cái này thì tớ cũng chưa chia sẻ lắm phần tác giả nói ở các trang web khác recommendation theo kiểu popularity thế nào @@.

Hoặc là sort theo ngày chẳng hạn.

Thôi để đọc có lẽ sẽ hiểu ý kỹ hơn =.=

Về association builder thì có lẽ toàn toán học, có lẽ cũng phải tham khảo thêm để hiểu dễ hơn =.=

Code viết ác liệt quá hự.

Còn về chạy code thì tớ sẽ để sau :-?

Dùng đoạn code tác giả cung cấp thì sẽ ra được các item liên quan theo kiểu association với 1 bộ phim như Figure 5.20. Details page showing the recommendations ^_^

Tạm thời tớ dùng cũng có vẻ gần hết 2 tiếng rồi =.= Thôi cứ làm tròn nhé.

Tớ nghĩ có thời gian đầu óc sẽ nghĩ được thêm và cảm nhận hơn về popularity, association recommendation.

Chúc Quang nhiều sức khỏe, buổi tối vui vẻ!!!

Chúc mọi việc gia đình Quang thuận lợi nhé!!!

Cảm ơn Quang đã đọc tới đây!!!

Về vụ nhiều chỗ trao đổi, nhiều thông tin quá thì cái đấy đương nhiên thui @@. Như ở chỗ cũ tớ làm thì có các kênh sau

Túm lại là mỗi người mỗi kiểu @@. Tài liệu rải rác mỗi nơi, chat rải rác mỗi nơi, viết rải rác mỗi nơi :(

Tớ thấy tiếc nhất là hình như Teams không cho backup thì phải =.= Hoặc là tớ chưa dành thời gian tìm hiểu xem để download hết message trong Teams thế nào.

Vì là có nhiều cái tớ viết hồi xưa dài trên đấy mà không backup được :(

Email thì có thể download về và lưu trữ offline, xem lại sau bằng Thunderbird free cũng okay.

Facebook at Work thì có thể export data mình ra dạng JSON được thì phải...

OneDrive for Business thì tài liệu trên đấy rùi nên là không sợ bị mất nữa... Và cũng download về được ý.

Đấy thì ở đâu cũng thế thui Quang O_O.

Cái cuối cùng mình cần có là Tài liệu và code.

Thông tin gì mà quan trọng là cứ phải lưu hết vào đấy chứ để trên chat là mất ý...

Tớ có thói quen là vậy...

Vậy thui.

Mẹ tớ vẫn đang mải mê cầm cái điện thoại, xem bao nhiêu người likes bài post trên Zalo về cái video ở trên haizzzz =.=

Giờ vẫn chưa được ăn nè :(. Huhu

Thôi cảm ơn Quang đọc đến đây nhé!!!

9health commented 1 year ago

Hello @quangvv9Life ,

Thanks Quang đã ngồi họp hôm nay với tớ và đã cùng xem lại Chương 4 và Chương 5 cũng như đưa ra nhiều câu hỏi liên quan tới tương lai nhé O_O.

Nói thật lúc đọc tớ cũng chỉ làm sao mình hiểu đúng ý tác giả thôi chứ áp dụng thì cũng chưa nghĩ đến.

Nguyên nhân là vì mình mà chưa hiểu làm sao mình có thể dùng lại được @@.

Vậy nên là cứ theo từng bước mà phát triển thôi, cũng không cần đốt cháy giai đoạn quá đâu.

Biết là nhanh mà tốt nhưng mà nhanh những lúc nào mới tốt, chậm lúc nào mới tốt thì cái đấy mới là đúng nhất O_O.

Tiếp tục về Chương 5

Thực sự thì hôm qua đọc Chương 5 xong tớ cũng chỉ mới hiểu 1/2 ý của tác giả thôi.

Còn phần Association thì cũng chưa hiểu hẳn lắm =.=

Sáng nay thì 5h40 tớ đã dậy được rồi và lại đắn đo xem là nên mở Manning ra đọc hay là tiếp tục đọc code nhỉ =.=

Thực sự hôm qua chưa dùng 5 phút free của Manning nữa.

Nếu mà mình lại đọc thì liệu khá khẩm hơn gì không =.=

Code nhìn 1 lần mà không hiểu chứng tỏ là mình có vấn đề hay tác giả viết có vấn đề.

Hình vẽ cũng y như thế.

Thôi thì cứ bám vào cái hình association của tác giả vẽ vậy rồi lao vào đọc code xem như thế nào :|.

Dù gì thì cũng review tính chất giao hoán là gì, tổ hợp là gì, chỉnh hợp là gì rồi...

Về đọc code Build Association Rules

Đầu tiên thì tớ đọc file này thôi

https://github.com/9health/moviegeek/blob/master/builder/association_rules_calculator.py

Vì đây chính là Python script cần chạy để ra được rules cho đúng.

Lúc này tớ cũng chưa hiểu ý tác giả muốn thế nào đâu vì nhìn mấy cái công thức toán học trên trang đấy khó hiểu quá =.=

def retrieve_buy_events():
    data = Log.objects.filter(event='buy').values()
    return data

def generate_transactions(data):
    transactions = dict()

    for transaction_item in data:
        transaction_id = transaction_item["session_id"]
        if transaction_id not in transactions:
            transactions[transaction_id] = []
        transactions[transaction_id].append(transaction_item["content_id"])

    return transactions

Đầu tiên là đọc hàm này trước.

Từ collector database lấy ra tất cả buy event.

Sau đó generate ra 1 ma trận kiểu như sau

def calculate_itemsets_one(transactions, min_sup=0.01):

    N = len(transactions)

    temp = defaultdict(int)
    one_itemsets = dict()

    for key, items in transactions.items():
        for item in items:
            inx = frozenset({item})
            temp[inx] += 1

    print("temp:")
    print(temp)
    # remove all items that is not supported.
    for key, itemset in temp.items():
        print(f"{key}, {itemset}, {min_sup}, {min_sup * N}")
        if itemset > min_sup * N:
            one_itemsets[key] = itemset

    return one_itemsets

Đến đoạn code này mới bắt đầu khó đây :-?

Đầu tiên là tác giả dùng defaultdict. Thật sự là thấy lần đầu luôn =.=

Tìm hiểu về defaultdict có thể xem ở trang này

https://docs.python.org/3/library/collections.html#collections.defaultdict

Setting the default_factory to int makes the defaultdict useful for counting (like a bag or multiset in other languages):

>>>
>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> sorted(d.items())
[('i', 4), ('m', 1), ('p', 2), ('s', 4)]

Dùng defaultdict(int) có thể hiểu ý muốn build kiểu dữ liệu xem tần suất (frequency) xuất hiện của item đấy là bao nhiêu.

Hàm frozenset cũng là thấy lần đầu luôn. Lại phải lần mò tiếp trên trang Python documents.

https://docs.python.org/3/library/stdtypes.html#types-set

There are currently two built-in set types, set and frozenset. The set type is mutable — the contents can be changed using methods like add() and remove(). Since it is mutable, it has no hash value and cannot be used as either a dictionary key or as an element of another set. The frozenset type is immutable and hashable — its contents cannot be altered after it is created; it can therefore be used as a dictionary key or as an element of another set.

Túm lại tác giả dùng frozenset ở đây là kiểu tập hợp (set) bị đóng băng hay là immutable (không thể thay đổi được, chả hiểu tớ dịch đúng không nữa @@).

Mục đích là vì dùng kiểu dict có key, value thì key là phải immutable @@.

Hiểu được 2 cái trên rồi thì cũng hòm hòm rồi. Có đủ khả năng hiểu hết rùi :-?

Ở 2 vòng for đầu tiên thì ý là lấy tất cả các Movie ID ra và đếm xem được dùng bao nhiêu lần!

Nói thêm 1 chút về hàm .items()

https://docs.python.org/3/tutorial/datastructures.html#dictionaries

When looping through dictionaries, the key and corresponding value can be retrieved at the same time using the items() method.

>>>
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
...     print(k, v)
...
gallahad the pure
robin the brave

Okay còn ở vòng lặp for tiếp theo thì có 1 đoạn if nhìn hơi khó hiểu.

Ở đây mặc định có lẽ N = số lượng transactionssup=0.01 hay hiểu sup = 1%

Nếu mà bộ phim ý có số lần đếm hơn 1% số lượng transactions thì mới được ghi nhận.

Đầu ra hàm này là one_itemset theo kiểu key, value có key là Movie ID còn value là số lần xuất hiện của bộ phim ý được buy trong database.

Chuyển tiếp sang hàm thứ khó hơn

def calculate_itemsets_two(transactions, one_itemsets):
    two_itemsets = defaultdict(int)

    for key, items in transactions.items():
        items = list(set(items))  # remove duplications

        if (len(items) > 2):
            for perm in combinations(items, 2):
                if has_support(perm, one_itemsets):
                    two_itemsets[frozenset(perm)] += 1
        elif len(items) == 2:
            if has_support(items, one_itemsets):
                two_itemsets[frozenset(items)] += 1
    return two_itemsets

def has_support(perm, one_itemsets):
    return frozenset({perm[0]}) in one_itemsets and \
           frozenset({perm[1]}) in one_itemsets

Dòng có comment # remove duplications thì có thể thử bằng lệnh như sau

>>> list(set([1,3,3,5]))
[1, 3, 5]

Đầu tiên nên xem lúc mà các Session ID mà có buy 2 phim đã.

Hàm has_support ở đây kiểm tra xem 2 bộ phim lấy ra từ Session ID đấy có nằm trong tập các phim xuất hiện hơn 1% không.

Nếu mà có thì ghi nhận cặp phim đấy @@.

Đối với Session ID có buy hơn 2 phim thì sẽ lấy tổ hợp chập 2 trong đống Movie ID có số lượng từ 3 đổ lên đấy ra và làm tương tự như trên...

Nói thêm 1 ít về hàm combinations

https://docs.python.org/3/library/itertools.html#itertools.combinations

def combinations(iterable, r):
    # combinations('ABCD', 2) --> AB AC AD BC BD CD
    # combinations(range(4), 3) --> 012 013 023 123

Okay vậy là đã xong hàm tính two_itemsets rồi. Đây chính là association rules mà sẽ được ghi vào database đó!!!

Giả sử đang vào link của bộ phim A chẳng hạn thì sẽ được giới thiệu theo association rule ra bộ phim X

Bộ phim X dựa vào association rule lưu ở trong database sẽ được giới thiệu ra bộ phim M và cứ tiếp như vậy...

Có thể thấy được theo association rule thì phim sẽ được recommend như thế nào trong Figure 5.20. Details page showing the recommendations

Quả thật là magic O_O.

Thuật toán diệu kì thật

def calculate_association_rules(one_itemsets, two_itemsets, N):
    timestamp = datetime.now()

    rules = []
    for source, source_freq in one_itemsets.items():
        for key, group_freq in two_itemsets.items():
            if source.issubset(key):
                target = key.difference(source)
                support = group_freq / N
                confidence = group_freq / source_freq
                rules.append((timestamp, next(iter(source)), next(iter(target)),
                              confidence, support))
    return rules

Sau khi hiểu kỹ hơn về one_itemsetstwo_itemsets thì đọc hàm này cũng sẽ dễ hiểu hơn.

2 vòng for là để lấy dữ liệu từ tần suất xuất hiện các bộ phim > 1% và các cặp phim.

Hàm issubset kiểm tra xem là tập này có phải là tập con của tập khác không

https://docs.python.org/3/library/stdtypes.html#frozenset.issubset

issubset(other)

set <= other Test whether every element in the set is in other. set < other Test whether the set is a proper subset of other, that is, set <= otherand set != other.

Có thể thử bằng đoạn code sau.

>>> s1={1,2,3}
>>> type(s1)
<class 'set'>
>>> s2={1,2}
>>> s2.issubset(s1)
True
>>> s1.issubset(s2)
False
>>> 

Giờ tớ mới hiểu kiểu set dùng có ưu điểm hơn kiểu dict thế nào đấy.

Check tập con thật là nhanh!!!

Tương tự đọc để hiểu hàm difference

https://docs.python.org/3/library/stdtypes.html#frozenset.difference

Return a new set with elements in the set that are not in the others.

Thử với đoạn code sau

>>> s2.difference(s1)
set()
>>> s1.difference(s2)
{3}

Từ đấy có thể hiểu source là Movie ID hiện tại còn target sẽ là Movie ID theo cặp đôi dấy để giới thiệu.

Phần tính toán supportconfidence có lẽ nhìn công thức toán học sẽ dễ hiểu hơn.

Ở đây tớ nghĩ phục vụ để kiểm tra xem thuật toán chạy ổn hay không.

Tớ hiểu confidence nghĩa là độ tin cậy. Nếu mà confidence > 1 có lẽ mình code thuật toán đúng đấy.

Còn confidence < 1 có vấn đề nào đó =.=

Xem thêm hình này Figure 5.14. Itemset lattice with four elements để dễ hiểu hơn về tập 1-phim và tập 2-phim.

support tớ nghĩ cũng nên lớn hơn 1 cơ mà chắc là nên đọc kỹ hơn quyển sách để hiểu cho rõ =.=

Đúng là sách do người châu Âu viết. Rất dễ hiểu và pratical =.=

Hàm nextiter tớ đang hiểu lấy ra phần tử thôi =.= Có lẽ thế

>>> list(s1)[0]
1
>>> next(iter(s1))
1
>>> s1
{1, 2, 3}
>>> type(s1)
<class 'set'>

Tớ có thử ở đây để mô phỏng lại. Hi vọng hiểu đúng =.=

Cuối cùng Rules sẽ được lưu lại ở đây

def save_rules(rules):

    for rule in rules:
        SeededRecs(
            created=rule[0],
            source=str(rule[1]),
            target=str(rule[2]),
            support=rule[3],
            confidence=rule[4]
        ).save()

Tìm hiểu thêm database model SeededRecs ở đây

https://github.com/9health/moviegeek/blob/master/recommender/models.py#L49-L64

class SeededRecs(models.Model):
    created = models.DateTimeField()
    source = models.CharField(max_length=16)
    target = models.CharField(max_length=16)
    support = models.DecimalField(max_digits=10, decimal_places=8)
    confidence = models.DecimalField(max_digits=10, decimal_places=8)
    type = models.CharField(max_length=8)

Tớ copy 1 ít ra ở đây để xem...

Và association rules được lấy ra và dùng ở đây

https://github.com/9health/moviegeek/blob/master/recommender/views.py#L21-L47

def recs_using_association_rules(request, user_id, take=6):
    events = Log.objects.filter(user_id=user_id)\
                        .order_by('created')\
                        .values_list('content_id', flat=True)\
                        .distinct()

    seeds = set(events[:20])

    rules = SeededRecs.objects.filter(source__in=seeds) \
        .exclude(target__in=seeds) \
        .values('target') \
        .annotate(confidence=Avg('confidence')) \
        .order_by('-confidence')

    recs = [{'id': '{0:07d}'.format(int(rule['target'])),
             'confidence': rule['confidence']} for rule in rules]

    print("recs from association rules: \n{}".format(recs[:take]))
    return JsonResponse(dict(data=list(recs[:take])))

Bộ phim được recommend theo kiểu association sẽ được trả về theo JSON và front-end parsing rồi hiển thị thôi.

Về next steps

Tớ chưa hiểu lắm là với set(events[:20]) khi đưa vào SeededRecs.objects.filter

Có lẽ tớ nên thử trên Python Django hự.

Cơ mà đang tính nên dùng GitHub Codespaces hay là thử ở local đây T_T

Và thử hết có lâu không, lâu quá thì...

Cơ mà cái này kiểu gì có lẽ cũng gặp nhiều nên là cũng có khi cần hiểu tương đối hix =.=

Ngoài ra thì tớ cũng chỉ dành 2 tiếng sáng nay để đọc và hiểu đống code này thôi, hiểu cả những kiểu dữ liệu chưa bao giờ dùng, những hàm chưa bao giờ dùng nữa T_T.

Công nhận là chương này ngốn thời gian thật đấy nhưng mà vẫn gặp và phải trải qua thôi hix hix.

Cảm giác khi đọc chương này giống như là đang học môn Thuật toán vậy @@.

Xưa tớ học Đại học thì không có môn nào kiểu thế riêng thì phải. Có lẽ bên Computer Science mới có...

Nếu mà implement trên hardware thì

Thật sự cái này mà viết lại bằng ngôn ngữ phần cứng bọn tớ hay dùng là Verilog thì chắc mất vài tháng mất =.=

Nếu mà làm cẩn thận ý, cả design và verify =.=

Riêng 1 cái mảng mà có cả trăm tới nghìn phần tử là phải dùng 1 con SRAM riêng rồi haizzz.

Mà trong này cứ có kiểu for rồi check xem phần tử đấy có trong mảng hay không...

Cái này mà code Verilog thì cũng lâu ghê đấy =.=

Nên là software viết trên CPU là đúng rồi hix. Quá là general với tất cả các loại thuật toán hix.

Thêm 1 chút về trải nghiệm đọc trên Manning

Hôm qua lúc viết cho Quang tớ có lưu ý về CPU power khi vào trang Manning.

Hôm nay tớ cũng lại lưu ý nữa =.=

Trang Manning tốn CPU power là do contact với nhiều tracker (theo dõi) hành vi người dùng quá =.= (Facebook, Amazon, Google haizzz)

Trang GitHub với OneDrive thì chả contact với tracker nào cả =.= thành ra là cứ để đấy chả tốn pin mấy =.=

Vậy là tớ cứ mở GitHub ra đọc thôi trong vòng 2 tiếng hình như đâu hết có 4% hay 5% pin thì phải @@. Chả hiểu tớ nhớ đúng không nữa. Hay là 10% nhỉ =.=

Trang Python docs cũng không contact tracker nào cả, nên cũng đỡ tốn CPU power...

Về 1 số việc khác

Sorry Quang tớ đùn đẩy cho Quang việc đăng ký cái Azure offer =.=

Cơ mà tớ cũng không biết lý do hợp lý là gì nữa nhưng mà tớ nghĩ là nhỡ tớ sau này làm sao Quang còn biết cách mà setup chứ =.=

Với cả tớ cũng không thích kiểu làm lại cái gì mình làm rồi lắm :|

Sorry Quang nhé. Nói chung kể ra rất nhiều lý do chắc cũng không make sense lắm =.=

Hôm trước thì tớ có ngồi kiểm tra mấy cái Azure plan các thứ, subscription các thứ thì phát hiện ra bị dùng quá 15GB rồi.

Cơ mà tớ chưa tạo issue thôi.

Tớ cũng check qua rồi và có lẽ không có vấn đề gì, sẽ không bị trừ vào thẻ của tớ =.=

Còn máy ảo Linux hiện tại thì đang hết cỡ khoảng 1.3GB download và 1.4GB upload.

Tớ sẽ thông tin nhiều hơn trong issue đấy =.=

Mà dùng quá băng thông là bị charge tiền.

Dùng quá I/O Microsoft cho phép cũng bị charge tiền. I/O ở đây là đọc ghi vào ổ SSD ý @@. Tớ cũng chưa tính free quy ra là bao nhiêu GB nữa =.=

Cơ mà túm lại mọi thứ giờ vẫn $0 trên Azure Free @@.

Vậy thôi còn 1 cái nữa là có lẽ cuối năm đang kỳ nghĩ lễ nên chắc Quang xin video Azure Onboarding hôm trước chắc cũng khó :| Nếu không được thì thui vậy, không sao đâu Quang!!!

Hix tớ dành nhiều thời gian cho Quang quá mà file Ghi Nhận Cảm Xúc, future tớ vẫn chưa update :((((.

Thanks Quang đã đọc đến đây và good night!!!

Mai tớ sẽ đọc lại Chương 5 tiếp cho hiểu hơn!!!

9health commented 1 year ago

Hello @quangvv9Life,

Thanks Quang đã comment vào bài viết hôm trước cho tớ mà tớ vẫn chưa đọc hic T_T.

Mấy hôm ở quê lau nhà, lau ban công, lau lan can, lau cửa sổ, đốt lá, chạy bộ 3 km sau khi ăn tối làm người tớ cũng bị oải quá @@.

Cơ mà cũng cố gắng sáng nay dậy để có tiến độ =.=

Về GitHub Codespaces

Tớ cũng nghĩ mãi các cách thử thư viện Query của Django xem cái nào hợp lý nhất =.=

Nói chung tớ thường prefer cách mới hơn và cuối cùng là tốn công học cái GitHub Codespaces đấy cơ mà cũng có nhiều cái thú vị =.=

Tớ sẽ cố gắng khắc phục điểm yếu hix.

Về GitHub Codespaces thì tớ có tìm hiểu kỹ hơn những gì họ cho free

Công thức thì có thể xem kỹ hơn ở trang này

https://docs.github.com/en/billing/managing-billing-for-github-codespaces/about-billing-for-github-codespaces

Account plan                        Storage per month   Core hours per month
GitHub Free for personal accounts   15 GB-month         120

Về phần networking thì không thấy họ nói gì, có lẽ dùng bao nhiêu cũng được =.=

Tính kỹ thêm về giá cả thì nói chung 60-hour đấy sẽ tương ứng với $5 =.=

Cứ mỗi tháng sẽ được reset lại số giờ dùng đấy.

Dịch vụ cloud họ dùng tất nhiên là Azure rồi.

Cảm ơn Microsoft cho mỗi tháng free $5 T_T.

Về Dev Container

https://docs.github.com/en/codespaces/setting-up-your-project-for-codespaces/introduction-to-dev-containers#using-the-default-dev-container-configuration

Trước thì tớ cũng đã dùng GitHub Codespaces vài lần rồi và thấy mọi thứ tương đối là easy.

Nhưng mà nói thật trước khi dùng hẳn thì mình cứ đọc tài liệu cho chắc vì tớ bị cái lỗi là không hiện output ở integrated terminal =.=

Tớ có đọc và phát hiện ra 1 thuật ngữ rất hay là dev container.

Nghĩa là kiểu dùng môi trường docker để develop luôn =.=

Cái máy ảo mà GitHub tạo ra cho mình thực chất là 1 dev container chứa VSCode ở bên trong đấy...

Trước thì như tớ có chia sẻ với Quang và anh Công là setup ở Azure Containers khó vì nhìn các bước loằng ngoằng quá =.=

Cứ tưởng là develop sẽ không bao giờ dùng container, docker cơ mà giờ thì khác thật...

Dùng container là cách mà tạo ra môi trường để dev nhanh nhất luôn hix.

Và VSCode còn có trò là đồng bộ settings từ máy mình lên máy ảo đấy...

Thật sự thì đúng là mọi thứ rất là mới, rất là innovative hix

Tớ còn đi theo dài...

Về fix lỗi không hiện chữ ở Integrated Terminal

Như tớ có chia sẻ với Quang trước tớ dùng GitHub Codespaces bị một lỗi rất chuối là output ở Terminal không hiện ra gì =.=

Khi đọc xong phần hướng dẫn của GitHub Codespaces rồi tớ cũng biết thuật ngữ gọi cái cửa sổ đấy là Integrated Terminal.

Tớ mò mẫm trên mạng xem có ai bị không thì thấy có mấy hướng dẫn này

https://github.com/microsoft/vscode/issues/67803

https://github.com/microsoft/vscode/issues/146506

https://github.com/community/community/discussions/4760

https://code.visualstudio.com/docs/terminal/appearance#_gpu-acceleration

https://github.com/microsoft/vscode/issues/133710

Nói chung là có nhiều cách fix.

Tớ thì không đọc phần GPU các thứ thấy có vẻ là tắt đi hơi có vấn đề thật =.=

Liệu dùng CPU có tăng lên không???

Đọc tài liệu của VSCode online cũng không hiểu lắm thật =.=

Thấy có vẻ tăng CPU nên tớ cũng không thích lắm.

Tớ chọn cách chuyển sang dùng bản Insiders và kết quả là đúng là cái Integrated Terminal lại hiện ra 1 cách đẹp đẽ =.=

Cơ mà CPU thì lên cao ngất ngưởng luôn =.=

Thế là tớ cũng không thích rồi. Tốn pin =.=

Vậy thì đành phải chuyển về bản như bình thường, Stable vậy.

Cơ mà chuyển về Stable thì lại chả thấy tab Ports đâu.

Không tìm cách nào để view trang web Django luôn =.=

Haizzz.

Tớ mò mẫm 10 rồi 15 phút không ra được nản quá hức

https://github.com/microsoft/vscode/issues/168205

Mẹ tớ gọi ra ăn sáng rồi, thôi vậy là 1 tiếng 30 phút mình đã trôi qua cũng gọi là hơi phí hay không phí đây hix.

Tớ stop, start máy ảo mãi không lần. Cũng tiếc không muốn xóa nhưng mà không có cách gì fix được đành xóa thôi :(.

Về next steps

Có vẻ như tớ có khả năng bôi những thứ gì đơn giản ra nhiều thứ và kéo dài thời gian ra =.=

Từ xưa đã như thế rồi.

Từ đầu mà cứ tạo trên máy ảo có phải hơn không. Ports cũng mở rồi =.=

Haizzz thôi thì tớ cũng nghĩ mãi mình làm cái gì sai ở đây nhỉ?

Liệu dùng GitHub Codespaces có đáng không?

À cái phần Dev Container ở trên tớ cũng chưa dám đọc kỹ lắm vì sợ tốn thời gian với đi xa quá hix =.=

Thôi kệ vậy.

Tớ nhớ lại Django Tutorial hồi xưa học ở W3Schools cùng với Quang

https://github.com/9health/django-tut-w3c

Thôi thì tớ sẽ blend hết mọi thứ lại.

Tớ sẽ vẫn dùng GitHub Codespaces và không cần xem terminal output ra như thế nào nữa =.=

Tớ sẽ thực hiện insert trên database bằng 1 cái button và load dữ liệu ra cũng bằng 1 cái button vậy =.=

Plan ban đầu là insert data tới SQLite3 database bằng command line cơ nhưng mà thôi vậy =.=

Nói chung hôm nay tớ thấy hơi đen vào ngày đầu năm mới.

Cơ mà thôi hi vọng ngày mai sáng sủa hơn.

Hi vọng là Quang ủng hộ tớ nhé hix.

Về Chương 5

Tớ vẫn còn 30 phút chưa dùng nữa, mà giờ quay lại Django thấy có vẻ mờ mịt quá, cần suy nghĩ kỹ hơn =.=

Thôi thì tớ nghĩ mình nên đọc Chương 5 xem thế nào.

18h30 tớ mới bắt đầu kế hoạch được =.=

Về trải nghiệm đọc trên Manning

Giờ tớ mới để ý hóa ra Manning cũng không phải unlock hết text đâu.

Có 2 đoạn văn vãn là scambled text.

Tớ lại dùng trò 5 phút free và copy hết text ra, mất khoảng 5 phút thôi.

Ctrl + C, Ctrl + V liên tục vào TextEdit trên macOS @@.

Tớ cũng đếm thử số chữ của Chương 5 thì thấy là có khoảng 7K từ @@.

Công nhận tác giả viết giỏi thật, chương nào cũng đúng 7K tới 8K từ chuẩn thật.

Còn về link ảnh thì cái nào tớ xem rồi và thấy quan trọng thì tớ lưu lại link đấy thôi.

Tớ quay vào TextEdit và đọc trên đấy cũng thấy thoải mái.

TextEdit của macOS có hỗ trợ Dark Mode dùng khá tốt @@.

Và nói chung dùng cũng đỡ tốn pin hơn là đọc trên liveBook của Manning nữa @@. Tổng cộng lúc đọc có 7 trackers chạy phía sau =.=

Càng nhiều trackers thì càng tốn CPU =.=

Ví dụ như vào hòm mail Outlook tại https://outlook.com thì tớ thấy Safari hiện có 32 trackers, tốn CPU kinh =.=

Về nội dung Chương 5

Tớ thấy tầm 7K từ tớ cũng nghĩ 30 - 45 phút là đọc xong thôi.

Cơ mà đúng như tớ dự đoán đoạn đầu đọc dễ dễ, tính popularity các thứ.

Cơ mà đọc đến phần tính association loằng ngoằng thật đấy =.=

Hiện tại tớ mới đọc xong 2 tiếng nên đầu tớ chưa tự xử lý được nhiều thứ hay ho.

Cơ mà đúng là đọc full-text không nhìn hình cũng thấy hiểu hơn những thứ mình từ suy ra =.=

1 khái niệm tớ hiểu được từ đấy thì là những gì non-personalized là những item mà luôn luôn giống với tất cả user @@.

Khi mình build association rule cũng là 1 cách tạo ra non-personalized recommendation vì là ai cũng sẽ hiện như thế =.=

Hiện tại tớ đang tạm dừng ở công thích tính Confidence. Cũng thấy khá hay.

Còn association rule chạy sẽ tốn CPU vì query từ database và xử lý cũng sẽ lâu vì thế thường sẽ chia ra làm 2 giai đoạn là

Như cách tác giả implement cũng có thể thấy là thực hiện đúng y như vậy.

Build rule riêng và chạy ra movie liên quan riêng.

Ví dụ như khi sort hàng chục nghìn hay hàng trăm nghìn bộ phim mà được nhiều người mua nhất chẳng hạn tác giả cũng bảo 1 ngày chạy 1 lần cũng không sao vì thời gian query từ database tương đối lâu.

Tạm thời thế đã =.=

Một vài suy nghĩ khác

Cảm ơn Quang đã đọc tới đây.

Sorry Quang đã gửi comment muộn.

Chúc Quang buổi tối vui vẻ hix!!!

Hi vọng mai mọi thứ sẽ okay O_O O_O O_O

9health commented 1 year ago

Hello @quangvv9Life,

Thanks Quang đã đọc bài viết hôm qua của tớ nhé mà tớ chưa kịp comment lại :(

Tớ thấy có email báo trong hòm mail rồi @@.

Tớ cũng biết vì sao GitHub không báo notification rồi =.= Thế nào mà option đấy bị unselected @@.

Thế cũng hay, mỗi lần nhìn thấy email mới hay là có tin nhắn mới, thông báo mới theo kiểu unexpected là tớ tim đập chân run @@@@@@. Hình như thế.

Sáng nay thì mẹ tớ dậy sớm quá, 5 giờ kém đã dậy rồi @@. Tớ cũng tỉnh rồi, vậy là tớ thức thôi @@.

Về tìm hiểu QuerySet trong Django

Qua tớ ngẫm nghĩ mãi xem mình có nên tiếp tục với GitHub Codespaces không =.= Hay ho thật nhưng mà cứ kiểu sao sao ấy =.= có vẻ có cái gì đó không thuận.

Cái tớ cần chỉ là hiểu mấy cái Filter Query của Django thôi mà theo hướng đấy có vẻ làm nhiều thứ quá.

Qua thì tớ đọc Chương 5 và có nhớ là tác giả bảo lúc mà hiện movies ra ở trang Home page ấy có thể sửa lại như sau để cho ra những bộ phim cũ nhất @@

Listing 5.5. Getting the newest movies first

movies = selected.movies.order_by('-year')

Cái này là làm cho vui thôi chứ thực tế người ta sẽ thích xem phim mới hơn.

Cơ mà cũng chưa chắc đã thích xem phim thật là mới như tác giả có bảo thế @@.

Một số trang web như mua đồ cổ thì cái gì càng cổ có khi hiện ra lại hay hơn =.=

Tác giả cũng khuyên là không nên sắp xếp theo thứ tự trong database nữa

Vậy là từ đoạn code trên tớ nghĩ là tốt nhất mình nên tập trung vào cái web app MovieGEEKs của mình để thử vậy.

Cái GitHub Codespaces kia biết được dev container là hay ho rồi.

Mà cái VSCode bản web có vẻ không thân thiện với tớ lắm. Tớ hay ấn lung tung quá thành ra mất cái này cái nọ =.=

Mà cũng tốn CPU lúc dùng nữa.

Dùng Terminal mặc định của macOS đỡ tốn hơn =.=

Thôi chắc tớ không có duyên với mấy cái IDE rồi, lại quay lại terminal và debug trên ý hự hự.

Lại theo cách nông dân vậy...

Về MovieGEEKs web app bị dừng

Tớ thì phát hiện ra cái web server bị down từ tối hôm qua rồi nhưng chưa hiểu tại làm sao @@.

Lại do Quang như lần trước hay là vì 1 lý do gì đó =.=

Mà tớ thì lại đang cần dùng vì không còn đi theo hướng GitHub Codespaces nữa.

Vậy là tớ lao vào điều tra như trong Issues này đây @@.

Cơ mà kết quả là không ra gì cả :(

Chắc là phải hỏi Quang mới rõ ngọn ngành @@.

Công nhận 1 mình tớ dùng không sao cơ mà thêm 1 hay 2 hay nhiều users hơn sẽ phát sinh vấn đề ^_^

Cái này mình cứ giải quyết dần thôi.

Vậy là tớ mất 30 phút để kiểm tra mấy cái log như trong Issue trên.

Rồi tớ nghĩ tốt nhất nên tạo 1 user độc lập để chỉ chạy web server và chỉ cho tớ dùng thôi như ở Tasks này

Tớ nghĩ làm như vậy thì Quang sẽ không còn bị vào nhầm folder, cài đặt nhầm environment nữa @@.

Đúng là dễ nhầm thật vì là tên giống nhau @@.

Về Linux administration

Nói thật về tạo user, tạo group các thứ tớ cũng có ít kinh nghiệm rùi vì trước tớ cài tool cho công ty là chia nhiều người nhiều folder khác nhau =.=

Hồi ở Yamanashi tớ làm trên Linux server dùng mấy cái tool vi mạch cũng được các bác tạo sẵn rùi.

Ở chỗ tớ làm ở Nhật có 1 cái hay là cùng 1 work (project đúng hơn) folder ai cũng có quyền đọc ghi hết kể cả folder người khác.

Và cũng nhìn thấy hết home folder người khác luôn.

Mà hồi xưa tớ dùng Fedora 14 (2010) thì không có trò dấy @@.

User nào là xem home folder user đấy thôi.

Do permission mặc định mà...

Tớ thì nói chung chỉ quen dùng 1 mình nên cũng chả để ý lắm mấy cái chia folder, chia permission read, write các thứ =.=

Cơ mà nói thật là nhiều user phải học thật mà tớ cũng lười.

Tớ thì không gây ra vụ nào kiểu to tát cả.

Chỉ 1 lần gần release project thì tớ chạy nhầm lệnh rm -rf và xong cái folder testcases tớ bay mất.

Mà không có bản backup nào luôn =.=

Recover trên Linux thì có khả năng nhưng mà nói chung cũng khá loằng ngoằng =.=

Các bác cũng thử giúp tìm hiểu recover giúp tớ mà không được =.=

May mà sau 1 tuần tớ vẫn còn nhớ đống test patterns đấy và tạo lại được.

Dự án không bị làm sao chứ như vụ dấy chắc delay 1-2 tuần =.=

May tớ làm module cũng không quá to nữa.

Sau vụ đấy tớ thấy sợ quá, vậy là viết test patterns hay môi trường hay gì tớ đều cho lên svn hết ở folder work của tớ =.=

Các bác ý thì cũng có lúc dùng svn, cũng có lúc không dùng. Chắc sợ mọi người không quen =.=

Nói chung svn cũng khá là loằng ngoằng cơ mà tớ cũng tiếp xúc 1 ít ít rồi với cả các bác cũng không đặt nặng quá tiến độ, tớ vừa tạo test pattern, vừa học lệnh svn thôi =.=

Cuối cùng cũng làm được, nhớ được nhiều cái @@, dùng được nên chuyển qua git cũng không tốn thời gian mấy @@.

Nhờ có svn thì mới có 1 folder repository lưu hết lại code môi trường, test case của mình chứ không thì lại remove nhầm thì chết =.=

Còn 1 em khác làm ở Shibuya tớ nghe kể chuyện hình như skill Linux em ý cũng không thạo lắm.

Em ý rm nhầm 1 cái folder gì mà chung cho dự án cơ và thế là =.=

Không hiểu chuyện gì xảy ra nữa.

Vì cái đấy ảnh hưởng tới nhiều người @@.

Hi vọng Quang đọc log trên của tớ cũng sẽ hiểu qua qua

Và hi vọng là sẽ sự cố bị tắt web server trong tương lai ít đi.

Nói chung dùng nhiều user tớ thấy cũng có cái hay, vào nhầm folder người khác mà nhỡ có thay đổi gì (write) thì sẽ có dòng này xuất hiện

ninehealth@LinuxVM15:~/work/moviegeek_webserver$ touch aa.txt
touch: cannot touch 'aa.txt': Permission denied

ninehealth@LinuxVM15:~/work/moviegeek_webserver$ echo hello > hello.txt
-bash: hello.txt: Permission denied

Quang có thể mới chưa quen nhưng mà có thể bắt chước tớ làm theo @@.

Hơi lâu cơ mà tớ thấy cũng có ích hự.

Thật ra tớ cũng là newbie thui ý mà =.=

Biết hơn có tí vì thực hành nhiều hơn =.=

Folder nào quan trọng là phải đặt permission quan trọng.

ninehealth@LinuxVM15:~/work/moviegeek_webserver$ ls -alhrt

total 176M

-rw-rw-r--  1 webserver  webserver   11K Dec 13 06:57 README.md
-rw-rw-r--  1 webserver  webserver  1.1K Dec 13 06:57 LICENSE
-rw-rw-r--  1 webserver  webserver   150 Dec 13 06:57 Dockerfile
-rw-rw-r--  1 webserver  webserver   341 Dec 13 06:57 .travis.yml
-rw-rw-r--  1 webserver  webserver   156 Dec 13 06:57 .gitignore
drwxrwxr-x  4 webserver  webserver  4.0K Dec 13 06:57 templates
drwxrwxr-x  4 webserver  webserver  4.0K Dec 13 06:57 static
-rw-rw-r--  1 webserver  webserver  3.1K Dec 13 06:57 populate_sample_of_descriptions.py
-rw-rw-r--  1 webserver  webserver  1.9K Dec 13 06:57 populate_ratings_from_MovieLens_data.py
-rw-rw-r--  1 webserver  webserver  1.2K Dec 13 06:57 populate_ratings.py
-rw-rw-r--  1 webserver  webserver  1.8K Dec 13 06:57 populate_moviegeek.py
-rw-rw-r--  1 webserver  webserver  6.0K Dec 13 06:57 populate_logs.py
drwxrwxr-x  2 webserver  webserver  4.0K Dec 13 06:57 notebooks
-rwxrwxr-x  1 webserver  webserver   254 Dec 13 06:57 manage.py
drwxrwxr-x  2 webserver  webserver  4.0K Dec 13 06:57 evaluator
-rw-rw-r--  1 webserver  webserver   839 Dec 13 06:57 docker-compose.yml
-rwxrwxr-x  1 webserver  webserver   230 Dec 13 06:57 db-migrate.sh
drwxrwxr-x  2 webserver  webserver  4.0K Dec 13 06:57 test
-rw-rw-r--  1 webserver  webserver    58 Dec 13 07:16 .prs
drwxrwxr-x  6 webserver  webserver  4.0K Dec 13 07:33 venv_3.6.9
-rw-rw-r--  1 webserver  webserver   578 Dec 13 07:39 requirements.txt
drwxrwxr-x  4 webserver  webserver  4.0K Dec 14 09:53 recommender
drwxrwxr-x  3 webserver  webserver  4.0K Dec 14 09:53 moviegeeks
drwxrwxr-x  4 webserver  webserver  4.0K Dec 14 09:53 collector
drwxrwxr-x  4 webserver  webserver  4.0K Dec 14 09:53 analytics
drwxrwxr-x  3 webserver  webserver  4.0K Dec 14 09:53 recs
drwxrwxr-x  8 webserver  webserver  4.0K Dec 15 19:53 .git
drwxrwxr-x  3 webserver  webserver  4.0K Dec 19 11:55 prs_project
drwxrwxr-x  3 webserver  webserver  4.0K Dec 27 21:25 builder
-rw-r--r--  1 webserver  webserver   61M Dec 27 21:25 db_02_implicit_ratings.sqlite3
-rw-r--r--  1 webserver  webserver   61M Dec 27 21:25 db_01_populate.sqlite3
lrwxrwxrwx  1 webserver  webserver    15 Dec 27 21:36 db.sqlite3 -> db_real.sqlite3
drwxrwxr-x  9 ninehealth ninehealth 4.0K Jan  4 06:00 ..
-rw-r--r--  1 webserver  webserver   55M Jan  4 10:37 db_real.sqlite3
drwxrwxr-x 16 webserver  webserver  4.0K Jan  4 10:37 .

Nhìn vào đây thì Quang có thể thấy 3 permission cho owner, group, others.

Ví dụ như file db_real.sqlite3 thì chỉ có user webserver mới có quyền đọc, ghi thôi do thuộc tính là -rw-r--r--

Như folder recs thì user ninehealth có quyền đọc thôi, drwxrwxr-x @@

User ninehealth và user webserver cùng chung 1 group là ninehealth.

Nhìn vào permission ở trên thì user ninehealth không thể modify folder này rồi =.=

Cơ mà nếu login từ user webserver thì


ninehealth@LinuxVM15:~/work/moviegeek_webserver$ sudo su webserver

webserver@LinuxVM15:/home/ninehealth/work/moviegeek_webserver$ cd ..

webserver@LinuxVM15:/home/ninehealth/work$ cd moviegeek

webserver@LinuxVM15:/home/ninehealth/work/moviegeek$ ls -alhrt

total 176M

-rw-rw-r--  1 ninehealth ninehealth  11K Dec 13 06:57 README.md
-rw-rw-r--  1 ninehealth ninehealth 1.1K Dec 13 06:57 LICENSE
-rw-rw-r--  1 ninehealth ninehealth  150 Dec 13 06:57 Dockerfile
-rw-rw-r--  1 ninehealth ninehealth  341 Dec 13 06:57 .travis.yml
-rw-rw-r--  1 ninehealth ninehealth  156 Dec 13 06:57 .gitignore
drwxrwxr-x  4 ninehealth ninehealth 4.0K Dec 13 06:57 templates
drwxrwxr-x  4 ninehealth ninehealth 4.0K Dec 13 06:57 static
-rw-rw-r--  1 ninehealth ninehealth 3.1K Dec 13 06:57 populate_sample_of_descriptions.py
-rw-rw-r--  1 ninehealth ninehealth 1.9K Dec 13 06:57 populate_ratings_from_MovieLens_data.py
-rw-rw-r--  1 ninehealth ninehealth 1.2K Dec 13 06:57 populate_ratings.py
-rw-rw-r--  1 ninehealth ninehealth 1.8K Dec 13 06:57 populate_moviegeek.py
-rw-rw-r--  1 ninehealth ninehealth 6.0K Dec 13 06:57 populate_logs.py
drwxrwxr-x  2 ninehealth ninehealth 4.0K Dec 13 06:57 notebooks
-rwxrwxr-x  1 ninehealth ninehealth  254 Dec 13 06:57 manage.py
drwxrwxr-x  2 ninehealth ninehealth 4.0K Dec 13 06:57 evaluator
-rw-rw-r--  1 ninehealth ninehealth  839 Dec 13 06:57 docker-compose.yml
-rwxrwxr-x  1 ninehealth ninehealth  230 Dec 13 06:57 db-migrate.sh
drwxrwxr-x  2 ninehealth ninehealth 4.0K Dec 13 06:57 test
-rw-rw-r--  1 ninehealth ninehealth   58 Dec 13 07:16 .prs
drwxrwxr-x  6 ninehealth ninehealth 4.0K Dec 13 07:33 venv_3.6.9
-rw-rw-r--  1 ninehealth ninehealth  578 Dec 13 07:39 requirements.txt
drwxrwxr-x  4 ninehealth ninehealth 4.0K Dec 14 09:53 recommender
drwxrwxr-x  3 ninehealth ninehealth 4.0K Dec 14 09:53 moviegeeks
drwxrwxr-x  4 ninehealth ninehealth 4.0K Dec 14 09:53 collector
drwxrwxr-x  4 ninehealth ninehealth 4.0K Dec 14 09:53 analytics
drwxrwxr-x  3 ninehealth ninehealth 4.0K Dec 14 09:53 recs
drwxrwxr-x  8 ninehealth ninehealth 4.0K Dec 15 19:53 .git
drwxrwxr-x  3 ninehealth ninehealth 4.0K Dec 19 11:55 prs_project
drwxrwxr-x  3 ninehealth ninehealth 4.0K Dec 27 21:25 builder
-rw-r--r--  1 ninehealth ninehealth  61M Dec 27 21:25 db_02_implicit_ratings.sqlite3
-rw-r--r--  1 ninehealth ninehealth  61M Dec 27 21:25 db_01_populate.sqlite3
lrwxrwxrwx  1 ninehealth ninehealth   15 Dec 27 21:36 db.sqlite3 -> db_real.sqlite3
-rw-r--r--  1 ninehealth ninehealth  55M Jan  2 19:47 db_real.sqlite3
drwxrwxr-x 16 ninehealth ninehealth 4.0K Jan  2 19:47 .
drwxrwxr-x  9 ninehealth ninehealth 4.0K Jan  4 06:00 ..

webserver@LinuxVM15:/home/ninehealth/work/moviegeek$ groups
ninehealth webserver

Vì priority group (cái này tớ không sure lắm đâu).

Có 1 lệnh là chgrp (change group) hay change ID gì đó xưa tớ thấy các bác ở Yamanashi hay dùng mà không hiểu vì sao -.-

webserver@LinuxVM15:/home/ninehealth/work/moviegeek$ groups ninehealth
ninehealth : ninehealth adm dialout cdrom floppy sudo audio dip video plugdev lxd netdev

Đại khái là user mình thuộc nhiều groups thì mình có thể chọn group đầu tiên là gì :-?

Chắc là tớ sẽ thử sau này

Cơ mà nhìn vào group và nhìn vào permission như trên.

Thì user webserver có lẽ sẽ có quyền đọc ghi (read + write) folder moviegeek đấy.

Cơ mà nếu bị đổi group thành webserver ở phía trước thì có lẽ sẽ không còn đọc, ghi được nữa @@.

Tớ phỏng đoán vậy thôi.

Cái này Google gọi là primary group @@. Chắc ngồi thử cũng mất 15-20 phút rồi report nữa...

https://unix.stackexchange.com/questions/151113/how-to-change-primary-group

Thôi để sau vậy :|.

Tạm thời như vậy tương đối ổn. hix

Về HTTP/3

Thì phần kiểm tra lỗi, tạo group mới, user mới, permission cho folder mới tớ làm hết trong vòng hơn 1 tiếng.

Tớ ra nghỉ giải lao 1 lúc thì tự dưng nhớ tới cái Private Relay của Apple =.=

Không hiểu có ảnh hưởng gì tới việc MovieGEEKs website không vào được trên ý không @@.

https://support.apple.com/en-us/HT212614

https://developer.apple.com/support/prepare-your-network-for-icloud-private-relay

Lại mải miết đọc mải miết đọc thấy có 1 cái là lạ là QUICHTTP/3

Lại mải miết đọc tiếp @@

https://www.cloudflare.com/en-gb/learning/performance/what-is-http3/

https://blog.cloudflare.com/http3-the-past-present-and-future/

Nói chung cũng khá là hay.

HTTP/3 kết hợp với QUIC làm cho vào web an toàn hơn @@.

HTTP/2 thì làm cho vào web nhanh hơn nhờ tạo ra nhiều thread để GET data @@.

Về hiển thị Home page của MovieGEEKs web app

Hix đọc linh tinh 1 hồi tớ quay về chủ đề chính.

Làm sao để hiển thị oldest movie như gợi ý tác giả trong Chương 5 @@.

Listing 5.5. Getting the newest movies first

movies = selected.movies.order_by('-year')

Đoạn code ví dụ tác giả đưa ra tớ chưa hề biết ở đâu luôn.

https://github.com/9health/moviegeek/blob/master/templates/moviegeek/index.html

Đầu tiên tớ đọc code front-end như thế nào cơ mà cũng rối =.= 10-15 phút không ra gì

Đúng là mình không có gen front-end.

Quay ra tiếp vào lại trang MovieGEEKs home page, bặt Firefox Web Developer Tools lên, vào tab Network xem liệu có gì khả quan để mò ra được cái đống movies ở giữa hiển thị ra thế nào không.

http://ninehealth.westus.cloudapp.azure.com:8080

Cũng không khả quan lắm =.=

Chỉ thấy gọi 1 đống thông tin từ TMDB thôi...

Thôi mò tiếp vào phần folder moviegeeks xem vậy vì có thấy dòng code này ở file index.html ở trên

        {% if movies %}
            {% for movie in movies %}
                {% if movie.movie_id %}getinfo('{{movie.movie_id}}', '{{movie.title}}');{% endif %}
            {% endfor %}
        {% endif %}

Search thử movie_id trong repository thì ra được file này.

https://github.com/9health/moviegeek/blob/master/moviegeeks/models.py

class Genre(models.Model):
    name = models.CharField(max_length=64)

    def __str__(self):
        return self.name

class Movie(models.Model):
    movie_id = models.CharField(max_length=16, unique=True, primary_key=True)
    title = models.CharField(max_length=512)
    year = models.IntegerField(null=True)
    genres = models.ManyToManyField(Genre, related_name='movies', db_table='movie_genre')

    def __str__(self):
        return self.title

Xem phần models của database như thế nào :-?

Xem tiếp phần API hay URL thế nào nữa

https://github.com/9health/moviegeek/blob/master/moviegeeks/urls.py

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^movie/(?P<movie_id>\d+)/$', views.detail, name='detail'),
    url(r'^genre/(?P<genre_id>[\w-]+)/$', views.genre, name='genre'),
    url(r'^search/$', views.search_for_movie, name='search_for_movie'),
]

Xem đăng ký ở project Django thế nào

https://github.com/9health/moviegeek/blob/master/prs_project/urls.py

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^movies/', include('moviegeeks.urls')),
    url(r'^collect/', include('collector.urls')),
    url(r'^analytics/', include('analytics.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^rec/', include('recommender.urls'))
]

Chà đoạn bắt pattern ^movies/ sẽ được mapp với function urls trong app moviegeeks

Hay ho đây :-?

Kiểm tra 1 chút phần database moviegeeks trong SQLite3 như thế nào

sqlite> SELECT * FROM moviegeeks_movie LIMIT 10;

movie_id    title                                    year      
----------  ---------------------------------------  ----------
0000008     Edison Kinetoscopic Record of a Sneeze   1894      
0000010     La sortie des usines Lumière             1895      
0000012     The Arrival of a Train                   1896      
25          The Oxford and Cambridge University Boa  1895      
0000091     Le manoir du diable                      1896      
0000131     Une nuit terrible                        1896      
0000417     A Trip to the Moon                       1902      
0000439     The Great Train Robbery                  1903      
0443        Hiawatha, the Messiah of the Ojibway     1903      
0000628     The Adventures of Dollie                 1908      

====================================================

sqlite> SELECT * FROM moviegeeks_genre;

id          name
----------  -----------
1           Documentary
2           Short
3           Horror
4           Comedy
5           Action
6           Adventure
7           Fantasy

Kiểm tra tra tiếp bảng tham chiếu Genre và Movie

sqlite> SELECT * FROM movie_genre LIMIT 10;

id          movie_id    genre_id  
----------  ----------  ----------
1           0000008     1         
2           0000008     2         
3           0000010     1         
4           0000010     2         
5           0000012     1         
6           0000012     2         
7           0000091     2         
8           0000091     3         
9           0000131     2         
10          0000131     4         

sqlite> SELECT * FROM movie_description LIMIT 10;

sqlite> 

Kiểm tra xem table movie_description ở đâu

https://github.com/9health/moviegeek/blob/master/recommender/models.py

class MovieDescriptions(models.Model):
    movie_id = models.CharField(max_length=16)
    imdb_id = models.CharField(max_length=16)
    title = models.CharField(max_length=512)
    description = models.CharField(max_length=1024)
    genres = models.CharField(max_length=512, default='')
    lda_vector = models.CharField(max_length=56, null=True)
    sim_list = models.CharField(max_length=512, default='')

    class Meta:
        db_table = 'movie_description'

    def __str__(self):
        return "{}: {}".format(self.imdb_id, self.title)

recommender app rồi, thôi bỏ qua...

Kiểm tra xem hiển thị trên Home page có giống như trong database không @@

sqlite> SELECT * FROM moviegeeks_movie ORDER BY year DESC LIMIT 10;

movie_id    title           year      
----------  --------------  ----------
0293429     Mortal Kombat   2021      
0499097     Tom Clancy&x27  2021      
0870154     Jungle Cruise   2021      
0993840     Army of the De  2021      
1160419     Dune: Part One  2021      
1321510     In the Heights  2021      
01361336    Tom and Jerry   2021      
1361336     Tom and Jerry   2021      
1461238     Kurt Vonnegut:  2021      
1697800     Die in a Gunfi  2021      

Đây là lệnh bên Python Django

https://github.com/9health/moviegeek/blob/master/moviegeeks/views.py

@ensure_csrf_cookie
def index(request):

    genre_selected = request.GET.get('genre')

    api_key = get_api_key()

    if genre_selected:
        selected = Genre.objects.filter(name=genre_selected)[0]
        movies = selected.movies.order_by('-year', 'movie_id')
    else:
        movies = Movie.objects.order_by('-year', 'movie_id')

    genres = get_genres()

Kiểm tra ở page 1 vài item có vẻ giống giống nhưng page 2 thì khác hẳn =.=

Lệnh SQL của tớ có vấn đề rồi, cần sort theo movie_id mới ra giống =.=

Đây là API gọi thông tin phim ở trang 1

https://api.themoviedb.org/3/find/tt0870154?external_source=imdb_id&api_key=<< removed >>

{
    "movie_results": [
        {
            "adult": false,
            "backdrop_path": "/7WJjFviFBffEJvkAms4uWwbcVUk.jpg",
            "id": 451048,
            "title": "Jungle Cruise",
            "original_language": "en",
            "original_title": "Jungle Cruise",
            "overview": "Dr. Lily Houghton enlists the aid of wisecracking skipper Frank Wolff to take her down the Amazon in his dilapidated boat. Together, they search for an ancient tree that holds the power to heal – a discovery that will change the future of medicine.",
            "poster_path": "/9dKCd55IuTT5QRs989m9Qlb7d2B.jpg",
            "media_type": "movie",
            "genre_ids": [
                28,
                12,
                14
            ],
            "popularity": 118.757,
            "release_date": "2021-07-28",
            "video": false,
            "vote_average": 7.479,
            "vote_count": 4785
        }
    ],
    "person_results": [],
    "tv_results": [],
    "tv_episode_results": [],
    "tv_season_results": []
}

Có thấy phim Jungle Cruise ở trang 1.

https://api.themoviedb.org/3/find/tt01361336?external_source=imdb_id&api_key=<< removed >>

{
    "movie_results": [],
    "person_results": [],
    "tv_results": [],
    "tv_episode_results": [],
    "tv_season_results": []
}

Cơ mà phim Tom & Jerry (2021) thì không thấy =.= Chắc TMDB có vấn đề =.=

Phim này cũng thấy

https://api.themoviedb.org/3/find/tt0499097?external_source=imdb_id&api_key=<< removed >>

{
    "movie_results": [
        {
            "adult": false,
            "backdrop_path": "/fPGeS6jgdLovQAKunNHX8l0avCy.jpg",
            "id": 567189,
            "title": "Tom Clancy's Without Remorse",
            "original_language": "en",
            "original_title": "Tom Clancy's Without Remorse",
            "overview": "An elite Navy SEAL uncovers an international conspiracy while seeking justice for the murder of his pregnant wife.",
            "poster_path": "/6GCOpT8QcNzup09TAMmvvk22LTR.jpg",
            "media_type": "movie",
            "genre_ids": [
                28,
                53
            ],
            "popularity": 81.008,
            "release_date": "2021-04-29",
            "video": false,
            "vote_average": 7.053,
            "vote_count": 2082
        }
    ],
    "person_results": [],
    "tv_results": [],
    "tv_episode_results": [],
    "tv_season_results": []
}

Phim này cũng thấy

https://api.themoviedb.org/3/find/tt0293429?external_source=imdb_id&api_key=<< removed >>

{
    "movie_results": [
        {
            "adult": false,
            "backdrop_path": "/9yBVqNruk6Ykrwc32qrK2TIE5xw.jpg",
            "id": 460465,
            "title": "Mortal Kombat",
            "original_language": "en",
            "original_title": "Mortal Kombat",
            "overview": "Washed-up MMA fighter Cole Young, unaware of his heritage, and hunted by Emperor Shang Tsung's best warrior, Sub-Zero, seeks out and trains with Earth's greatest champions as he prepares to stand against the enemies of Outworld in a high stakes battle for the universe.",
            "poster_path": "/6Wdl9N6dL0Hi0T1qJLWSz6gMLbd.jpg",
            "media_type": "movie",
            "genre_ids": [
                28,
                14,
                12
            ],
            "popularity": 156.763,
            "release_date": "2021-04-07",
            "video": false,
            "vote_average": 7.131,
            "vote_count": 5059
        }
    ],
    "person_results": [],
    "tv_results": [],
    "tv_episode_results": [],
    "tv_season_results": []
}

Đến đây cũng hết thời gian 2 tiếng rồi.

Vậy là giờ tớ đã hiểu Home page được render như thế nào rùi!!!

https://github.com/9health/moviegeek/blob/master/moviegeeks/views.py#L36

Chính là ở đây @@.

moviegeeks app sẽ đọc file moviegeek/index.html và render lại trang web home page cho mình xem!!!

Để thay đổi cách movie hiển thị ra ở trang Home page có thể sửa ở file trên!!!

Về next tasks

Có lẽ tớ sẽ thử xem như thế nào @@.

Cơ mà tìm hiểu thế này cũng thấy vui hơn rồi vì đúng hướng và hiểu MovieGEEKs web app hơn.

Hi vọng là mai mọi thứ lại đi đúng đường.

Còn về Chương 5 tớ vẫn chưa đọc thêm gì cả =.=

Sáng nay 8h mẹ tớ đi họp chi bộ rồi tham gia CLB hát.

Chắc 11h30 sẽ về =.=

Tớ thì mẹ đi là lau nhà, là lau phòng tắm, phòng vệ sinh @@, rửa nồi cơm @@.

Nay tớ thấy trời nắng đẹp @@.

Quang cho tớ sang xin bữa cơm nhé!!! Tớ tới chỗ EcoHome Phúc Lợi đây @@.

Cảm ơn Quang nhiều!!!

Nhiều vấn đề phát sinh quá ở Chương 5 cơ mà hi vọng mọi thứ sẽ okay!!!