"Đối diện với những thứ to lớn ta mới thấy mình thật nhỏ bé!" – Câu này của triết gia nào đó... hình như là của mình. Khi đối mặt với làn sóng thần AI hiện nay, mình mới chợt nhớ về những buổi học "Nhập môn AI" thời sinh viên năm 3, năm 4. Ngày ấy, mình chăm chỉ đến lớp không sót buổi nào – đơn giản vì nhà trọ không có điều hòa, không ngủ được đành phải đến lớp để... "học". Nhớ cái thời vô lo vô nghĩ, ngủ ngồi vẫn ngon lành, chẳng bù cho bây giờ mất ngủ triền miên.

Vì ngủ ngon quá nên sau này chẳng đọng lại được mấy kiến thức trên trường. Mình chỉ nhớ mang máng thầy có dạy về "Decision Tree" (Cây quyết định) cùng mấy công thức tính toán khô khan, có thể mấy cái công thức này chẳng khác gì mấy viên thuốc ngủ cả đưa mình vào giấc mơ mà khi tỉnh dậy thì... cây đã mất gốc.

Nay tự nhiên nổi hứng muốn tìm hiểu lại mấy cái căn bản cấu thành lĩnh vực AI – à không, chính xác hơn là Machine Learning. Mình thấy nó khá là hay ho mà không hiểu sao hồi đi học mình lại thấy nó như mấy viên thuốc ngủ. Giờ thì wake-up.

warning

Mình phải nói trước là mình không phải dân chuyên AI. AI, hay lĩnh vực nhỏ hơn là Machine Learning, trong mắt mình chỉ đơn giản là dự đoán kết quả. Mình hiểu AI là mô phỏng bộ não con người, một thứ vô cùng phức tạp. Nhưng theo cách đơn giản hóa vấn đề, nhiệm vụ chính của bộ não chúng ta hàng ngày là đưa ra quyết định (cuộc đời vốn là một chuỗi quyết định...). Bộ não dựa trên kiến thức, kinh nghiệm sẵn có để đưa ra các quyết định đó. Vậy nên, AI hay Machine Learning cũng tương tự: dựa vào kiến thức (dữ liệu) để dự đoán – đưa ra quyết định. Bài viết này mình viết với mục đích chia sẻ vui vui thôi, không mang tính học thuật gì cả nhé!

Tại sao các thuật toán Machine Learning lại đặc biệt?

Hãy lấy một ví dụ thực tế: mình muốn tạo một con chatbot. Khi bạn bè rủ đi đánh cầu lông, con bot này sẽ tự động ra quyết định thay mình rằng có nên đi hay không. Với lập trình truyền thống, mình sẽ làm như sau:

  1. Liệt kê các trường hợp cần cân nhắc:

    • Nếu trời mưa -> KHÔNG đi.
    • Nếu khoảng cách từ nhà đến sân cầu lông:
      • Xa:
        • Team không có nữ -> KHÔNG đi.
        • Team có nữ -> ĐI (thôi, xa tí cũng được =)).
    • Nếu thời gian hẹn là:
      • Buổi tối -> ĐI.
      • Ban ngày -> KHÔNG đi.
  2. Viết logic cho chatbot: Với các trường hợp trên, mình sẽ viết một đoạn mã đơn giản cho con chatbot:

    def should_play_badminton(input): # Thời tiết if is_raining: return False # Khoảng cách if distance == "far": if has_girl_on_the_team: return True # Thời điểm if time == "evening": # return time == "evening" return True else: return False
  3. Tạo bảng kết quả: Với logic trên và các đầu vào cần thiết, mình sẽ có bảng kết quả như sau (bảng này chỉ là một phần thôi, đầy đủ tất cả các case sẽ là 24 = 16 dòng):

    Thời tiếtKhoảng cáchCó nữ trong team?Thời gianĐi?
    MưaXaBuổi tốiKO
    Ko MưaGầnKhôngBuổi tốiĐi
    Ko MưaXaKhôngBuổi tốiKO
    Ko MưaGầnBan ngàyĐi
    Ko MưaXaBan ngàyĐi
    MưaGầnBuổi tốiKO
    Ko MưaGầnKhôngBan ngàyKO
    MưaXaKhôngBan ngàyKO
    Ko MưaXaBuổi tốiĐi
    MưaGầnKhôngBan ngàyKO
    ...............

Con chatbot với logic này có thể đưa ra quyết định thay mình rất tốt. Nhưng nếu thằng bạn mình thấy hay ho và cũng muốn dùng thì sao? Bạn có thể nhận ra rằng con chatbot kia chỉ "hoạt động" tốt với cá nhân mình. Muốn cho thằng bạn dùng, mình phải viết lại một đoạn logic khác dựa trên những ưu tiên của nó (khả năng cao là khác của mình). Làm sao mình có thể "thương mại hóa" con chatbot của mình nếu cứ mỗi một người dùng mới mình lại phải viết riêng một logic chứ?

Khác biệt giữa Lập trình truyền thống và Học máy

Để có thể "thương mại hóa" con chatbot của mình, mình cần một bước "tự động" viết ra logic cho mỗi người dùng, giúp con chatbot tự động thích nghi với từng cá nhân khác nhau. Điều này gần như bất khả thi nếu chỉ sử dụng lập trình thuần túy: nhận vào đầu vào -> áp dụng thuật toán/công thức -> đưa ra kết quả.

Trong Machine Learning thì ngược lại: chúng ta nhận vào kết quả và những gì đã tạo ra kết quả đó -> để tìm ra "cách xào nấu" (logic/thuật toán). Khi bạn đã tìm ra được "cách xào nấu" rồi, giờ chỉ cần đưa đầu vào là bạn có thể đưa ra kết quả.

Hãy hình dung sự khác biệt giữa lập trình thuần túy và học máy qua hai "bài toán" sau:

  • Bài toán Lập trình truyền thống:

    • Cho a và b, hãy đưa ra kết quả c là tổng của a và b.
    • Ở đây, với a và b, kết quả c luôn là a + b, không quan tâm a, b là số mấy. Quy trình là: Đầu vào + Áp dụng công thức (cộng) -> Kết quả.
  • Bài toán Học máy (Học từ dữ liệu):

    • Cho a, b và c, hãy tìm "phép tính" sao cho a 'phép tính' b = c.
    • Ở bài toán này, "phép tính" có thể là +, -, x, :... tùy thuộc vào a, b, c là gì.
    • Ví dụ dữ liệu đầu vào:
      • a = 1, b = 2 và c = 3
      • a = 2, b = 3 và c = 5
      • a = 3, b = 3 và c = 6
    • Với "đống" dữ liệu đầu vào này, Machine Learning sẽ "học" và tìm ra được "phép tính" ở đây là phép cộng (+). Khi đã tìm được "phép tính" rồi, giờ chỉ cần cho a = 4, b = 6 thì con bot sẽ suy ra c = a 'phép tính' b = 10.

Trở lại bài toán thương mại hóa con chatbot, giả sử thằng bạn của mình đưa cho mình một cái bảng "thống kê những lần nhận được lời mời đi đánh cầu lông" tương tự như bảng mình đã tạo ở trên, liệu có cách nào để con bot của mình suy ra được nó nghĩ gì khi nhận được lời mời đi đánh cầu lông không?

Áp dụng cho tất cả mọi người khi sử dụng chatbot: họ chỉ cần "upload" cái bảng thống kê kia lên, thì con chatbot của mình sẽ tự động đưa ra quyết định được cho các lần sau! Giờ thì bài toán ở đây là làm sao để con chatbot của mình học được từ dữ liệu của người dùng? Có một thuật toán đơn giản để làm việc đó: Cây quyết định.

Trồng cây

Để con chatbot của mình có thể tự động học từ dữ liệu của người dùng và đưa ra quyết định, chúng ta cần một thuật toán có khả năng "đọc" các quy tắc ẩn trong những dữ liệu đó. Cây Quyết Định (Decision Tree) chính là một trong những thuật toán cơ bản và dễ hiểu nhất làm được điều này. Hãy hình dung nó như một cây thư mục, mỗi nút là một câu hỏi (một điều kiện), và mỗi nhánh là câu trả lời dẫn đến câu hỏi tiếp theo, cho đến khi chúng ta đi đến một "lá" – nơi chứa quyết định cuối cùng.

Vậy làm thế nào mà cây này lại "mọc" ra được các câu hỏi và quyết định đúng đắn? Nó dựa vào việc phân tích sự không chắc chắn (impurity) trong dữ liệu. Và để đo lường sự không chắc chắn này, chúng ta cần đến một khái niệm quan trọng: Entropy.

Có thể bạn đã nghe, AI dựa trên nền tảng của xác suất thống kê, nên là sau đây mình sẽ tìm hiểu vài công thức có liên quan đến xác suất.

Entropy: Đo lường sự hỗn loạn của dữ liệu

Trong Machine Learning, Entropy là một thước đo cho sự "thuần khiết" hay "hỗn loạn" của một tập hợp dữ liệu.

  • Nếu một tập dữ liệu cực kỳ hỗn loạn nghĩa là bạn ko chắc chắn về kết quả đầu ra. Ví dụ có 1 túi bi gồm: 5 bi màu đỏ và 5 bi màu xanh, mỗi lần bạn bốc ngẫu nhiên 1 viên thì có 50% là viên màu đỏ và 50% là màu xanh. Bạn ko thể chắc chắn là viên bi đang được bốc ra là màu xanh hay màu đỏ. Dữ liệu trong túi là cực kỳ hỗn loạn nên Entropy trường hợp này sẽ cao.

  • Ngược lại, nếu một tập dữ liệu khá "thuần khiết" nghĩa là bạn gần như chắc chắn về kết quả đầu ra. Ví dụ: 1 túi bi có 9 viên bi đỏ và 1 viên bi xanh, mỗi lần bạn "thò tay" vào bốc thì 90% bạn sẽ bốc được bi màu đỏ, bạn dường như biết trước được kết quả rồi vì bốc 10 lần thì 9 lần là bi đỏ rồi. Entropy sẽ rất thấp trong trường hợp này vì dữ liệu khá là "thuần khiết" có 10% là tạp chất thôi.

Công thức tính Entropy nghe có vẻ phức tạp, nhưng ý tưởng đằng sau nó khá đơn giản:

H(S)=i=1cpilog2(pi)H(S) = - \sum_{i=1}^{c} p_i \log_2(p_i)

Trong đó:

  • H(S)H(S) là Entropy của tập dữ liệu SS.
  • cc là số lượng các lớp (kết quả) khác nhau trong SS (ví dụ: "Đi" và "KO").
  • pip_i là tỷ lệ của các trường hợp thuộc lớp thứ ii trong tập dữ liệu SS.

Hãy thử tính Entropy cho các ví dụ:

Ví dụ 1:

  • Xác suất bốc được bi đỏ (pđỏp_{đỏ}) = 5/10=0.55/10 = 0.5
  • Xác suất bốc được bi xanh (pxanhp_{xanh}) = 5/10=0.55/10 = 0.5

Áp dụng công thức Entropy:
H(S)=(pđỏlog2(pđỏ)+pxanhlog2(pxanh))H(S) = - (p_{đỏ} \log_2(p_{đỏ}) + p_{xanh} \log_2(p_{xanh}))
H(S)=(0.5log2(0.5)+0.5log2(0.5))H(S) = - (0.5 \log_2(0.5) + 0.5 \log_2(0.5))
H(S)=(0.5×1+0.5×1)H(S) = - (0.5 \times -1 + 0.5 \times -1)
H(S)=(0.50.5)H(S) = - (-0.5 - 0.5)
H(S)=(1)H(S) = - (-1)
H(S)=1H(S) = 1

Ví dụ 2:

  • Xác suất bốc được bi đỏ (pđỏp_{đỏ}) = 9/10=0.99/10 = 0.9
  • Xác suất bốc được bi xanh (pxanhp_{xanh}) = 1/10=0.11/10 = 0.1

Áp dụng công thức Entropy:
H(S)=(pđỏlog2(pđỏ)+pxanhlog2(pxanh))H(S) = - (p_{đỏ} \log_2(p_{đỏ}) + p_{xanh} \log_2(p_{xanh}))
H(S)=(0.9log2(0.9)+0.1log2(0.1))H(S) = - (0.9 \log_2(0.9) + 0.1 \log_2(0.1))
H(S)=(0.9×0.152+0.1×3.322)H(S) = - (0.9 \times -0.152 + 0.1 \times -3.322) (Làm tròn)
H(S)=(0.13680.3322)H(S) = - (-0.1368 - 0.3322)
H(S)=(0.469)H(S) = - (-0.469)
H(S)0.469H(S) \approx 0.469

Giá trị Entropy này thấp hơn nhiều so với trường hợp 5 bi đỏ 5 bi xanh, cho thấy dữ liệu có độ "thuần khiết" cao hơn.

Entropy có vai trò gì trong bài toán của mình chứ? Well, cái bảng thống kê mà mình muốn người dùng upload lên là tập 1 tập hợp các cases có thể xảy ra, nếu bằng cách nào đó mà mình chia nhỏ được tập hợp đó ra thành các tập hơn nhỏ hơn nhưng "thuần khiết" thì mình có thể suy ra được kết quả - "quyết định" của người đó.

isay

Với cái bảng "thống kê" bên trên ta có thể viết 16 dòng if để nó chia tập hợp đấy thành 16 tập hợp "thuần khiết" - đưa ra được kết quả.

def should_play_badminton(): if is_raining and distance == "far" and has_girl_on_the_team and time == "evening": return True if not is_raining and distance != "far" and not has_girl_on_the_team and time == "evening": return False # ...

Nhìn là biết cách này ko scalable rồi, đây là tập dữ liệu nhỏ, nếu bạn thêm một cột thôi (thuộc tính) mới ví dụ: cột mới là "Cuối tuần?" thì số lượng trường hợp phải xét bây giờ là 2 * 16 = 32 trường hợp (= 32 câu if).

Trong thuật toán nó gọi time-complexity cho cách này là O(n2): thêm một cột thì số lượng case phải xét x2 (exponential time), 1 bảng có n cột thì số lượng cases phải xét là 2n, 32 cột là 232 ~= 4 tỉ trường hợp phải xét.

Cây quyết định là thuật toán để giải quyết điều đó, cuối cùng thì nó vẫn là các dòng if thôi nhưng "most of the time" nó sẽ ko phải xét hết các trường hợp. Nguyên lý thì vẫn là chia nhỏ tập hợp thành các tập hợp nhỏ hơn nhưng "thuần khiết" để đưa ra được kết quả.

Bắt đầu từ gốc nó sẽ đặt câu hỏi để phân nhánh "làm sạch" dữ liệu, cho đến khi dữ liệu được "thuần khiết" nó sẽ đưa ra được "quyết định". Bài toán bây giờ lại trở thành, đặt câu hỏi gì để phân chia tập hợp bây giờ, mục đích là đặt càng ít câu hỏi càng tốt, nên nó phải tìm ra cái thuộc tính nào: "Thời tiết", "Khoảng cách"... ảnh hưởng nhiều nhất đến quyết định của mình. Nói đơn giản là làm cách nào mà nó suy ra được "nếu trời mưa thì 100% là mình KO ĐI", thì nó chỉ cần đặt câu hỏi "Trời có mưa ko?" nếu có thì nó sẽ ko quan tâm đến các thuộc tính khác mà ra quyết định luôn là: "KO", còn nếu "trời không mưa" thì nó sẽ đặt câu hỏi khác...

Làm sao để nó biết được nên đặt câu hỏi nào?

Information Gain (hỏi câu nào mang lại giá trị nhất)

Entropy giúp chúng ta đo lường sự hỗn loạn. Vậy làm sao để biết "câu hỏi" nào là tốt nhất để phân chia dữ liệu? Đó chính là lúc Information Gain (Độ lợi thông tin) phát huy tác dụng.

Information Gain đo lường mức độ giảm Entropy khi chúng ta chia tập dữ liệu SS theo một thuộc tính AA nào đó. Về cơ bản, nó cho biết thuộc tính nào mang lại nhiều thông tin nhất để phân loại các mẫu dữ liệu.

Công thức tính Information Gain như sau:

IG(S,A)=H(S)vValues(A)SvSH(Sv)IG(S, A) = H(S) - \sum_{v \in Values(A)} \frac{|S_v|}{|S|} H(S_v)

Trong đó:

  • IG(S,A)IG(S, A) là Information Gain của tập dữ liệu SS khi chia theo thuộc tính AA.
  • H(S)H(S) là Entropy của tập dữ liệu gốc SS.
  • Values(A)Values(A) là tập hợp tất cả các giá trị mà thuộc tính AA có thể nhận (ví dụ: với thuộc tính "Thời tiết" thì có "Mưa", "Không Mưa").
  • SvS_v là tập hợp con của SS mà thuộc tính AA có giá trị vv.
  • Sv|S_v| là số lượng phần tử trong tập con SvS_v.
  • S|S| là tổng số lượng phần tử trong tập dữ liệu gốc SS.

Mỗi khi xây dựng cây, thuật toán sẽ tính toán Information Gain cho tất cả các thuộc tính còn lại và chọn thuộc tính nào cho Information Gain cao nhất để làm nút phân chia tiếp theo. Quá trình này cứ lặp lại cho đến khi các nhánh đạt đến sự thuần khiết mong muốn hoặc không còn thuộc tính nào để phân chia nữa.

Cùng áp dụng công thức để xem thuộc tính "Thời tiết" mang lại Information Gain bao nhiêu cho cái bảng thống kê của mình!

Thời tiếtKhoảng cáchCó nữ trong team?Thời gianĐi?
MưaXaBuổi tốiKO
Ko MưaGầnKhôngBuổi tốiĐi
Ko MưaXaKhôngBuổi tốiKO
Ko MưaGầnBan ngàyĐi
Ko MưaXaBan ngàyĐi
MưaGầnBuổi tốiKO
Ko MưaGầnKhôngBan ngàyKO
MưaXaKhôngBan ngàyKO
Ko MưaXaBuổi tốiĐi
MưaGầnKhôngBan ngàyKO

Bước 1: Tính Entropy của tập dữ liệu gốc (H(S)H(S))

Trong 10 mẫu dữ liệu trên:

  • Có 4 trường hợp "Đi"
  • Có 6 trường hợp "KO"

Vậy:

  • pĐi=4/10=0.4p_{Đi} = 4/10 = 0.4
  • pKO=6/10=0.6p_{KO} = 6/10 = 0.6

H(S)=(0.4log2(0.4)+0.6log2(0.6))H(S) = - (0.4 \log_2(0.4) + 0.6 \log_2(0.6)) H(S)0.971H(S) \approx 0.971 (như đã tính ở phần Entropy)

Bước 2: Tính Entropy sau khi chia theo thuộc tính "Thời tiết"

Thuộc tính "Thời tiết" có 2 giá trị: "Mưa" và "Ko Mưa".

  • Nhóm "Thời tiết" = "Mưa" (có 4 mẫu):

    Thời tiếtKhoảng cáchCó nữ trong team?Thời gianĐi?
    MưaXaBuổi tốiKO
    MưaGầnBuổi tốiKO
    MưaXaKhôngBan ngàyKO
    MưaGầnKhôngBan ngàyKO
    • Kết quả "Đi": 0 mẫu
    • Kết quả "KO": 4 mẫu
    • Entropy(SMưaS_{Mưa}) = 0 (vì tất cả đều là "KO", rất thuần khiết)
  • Nhóm "Thời tiết" = "Ko Mưa" (có 6 mẫu):

    Thời tiếtKhoảng cáchCó nữ trong team?Thời gianĐi?
    Ko MưaGầnKhôngBuổi tốiĐi
    Ko MưaXaKhôngBuổi tốiKO
    Ko MưaGầnBan ngàyĐi
    Ko MưaXaBan ngàyĐi
    Ko MưaGầnKhôngBan ngàyKO
    Ko MưaXaBuổi tốiĐi
    • Kết quả "Đi": 4 mẫu
    • Kết quả "KO": 2 mẫu
    • pĐi=4/60.667p_{Đi} = 4/6 \approx 0.667
    • pKO=2/60.333p_{KO} = 2/6 \approx 0.333
    • Entropy(SKoMưaS_{KoMưa}) = (0.667log2(0.667)+0.333log2(0.333))- (0.667 \log_2(0.667) + 0.333 \log_2(0.333))
    • Entropy(SKoMưaS_{KoMưa}) 0.918\approx 0.918

Bước 3: Tính Information Gain cho thuộc tính "Thời tiết"

IG(S,Thời tieˆˊt)=H(S)(SMưaSH(SMưa)+SKoMưaSH(SKoMưa))IG(S, \text{Thời tiết}) = H(S) - \left( \frac{|S_{Mưa}|}{|S|} H(S_{Mưa}) + \frac{|S_{KoMưa}|}{|S|} H(S_{KoMưa}) \right)
IG(S,Thời tieˆˊt)=0.971(410×0+610×0.918)IG(S, \text{Thời tiết}) = 0.971 - \left( \frac{4}{10} \times 0 + \frac{6}{10} \times 0.918 \right)
IG(S,Thời tieˆˊt)=0.971(0+0.5508)IG(S, \text{Thời tiết}) = 0.971 - (0 + 0.5508)
IG(S,Thời tieˆˊt)0.4202IG(S, \text{Thời tiết}) \approx 0.4202

Kết quả Information Gain cho các thuộc tính khác (áp dụng công thức tương tự):

  • IG(S,Khoảng caˊch)0IG(S, \text{Khoảng cách}) \approx 0
    • Mẫu "Xa": 2 Đi, 3 KO
    • Mẫu "Gần": 2 Đi, 3 KO. => Cả hai nhóm đều không làm giảm Entropy đáng kể so với Entropy ban đầu.
  • IG(S,Coˊ nữ trong team?)0.1245IG(S, \text{Có nữ trong team?}) \approx 0.1245
    • Mẫu "Có": 3 Đi, 2 KO;
    • Mẫu "Không": 1 Đi, 4 KO.
  • IG(S,Thời gian)0IG(S, \text{Thời gian}) \approx 0
    • Mẫu "Buổi tối": 2 Đi, 3 KO
    • Mẫu "Ban ngày": 2 Đi, 3 KO. => Tương tự, không giảm Entropy đáng kể.

Dựa trên kết quả tính toán, thuộc tính "Thời tiết" có Information Gain cao nhất (0.4202\approx 0.4202). Điều này có nghĩa là, nếu chúng ta phân chia dữ liệu theo thuộc tính "Thời tiết", sự hỗn loạn trong các nhóm con sẽ giảm đi nhiều nhất. Do đó, Cây Quyết Định sẽ chọn "Thời tiết" làm nút gốc để bắt đầu quá trình phân loại.

Cứ thế tính toán tiếp thì ta sẽ build được một cái cây có thể giống bên dưới.

Thời tiết / \ / \ Mưa Ko Mưa | | | | KO Có nữ trong team? / \ / \ Có KO | / \ | / \ Đi Thời gian / \ / \ Buổi tối Ban ngày | | Đi KO

Kết luận

Mặc dù là cái căn bản trong thế giới AI - Machine Learning nhưng bài này giúp mình hiểu thêm nhiều về mấy câu sau:

  • 1.AI nặng về toán và xác suất thông kê. Ta thấy bảo các Decision Tree này là thuật toán đơn giản trong Machine Learning nhưng mà vẫn phức tạp hơn so với thuật toán lập trình thuần túy: sort, search... Và nó nặng về kiến thức toán học và xác suất thống kê nhiều.

  • 2.AI "đói" dữ liệu. Càng nhiều dữ liệu thì kết quả càng đúng. Ví dụ đơn giản là cái bài toán tìm 'phép tính'. Nếu tập input a=2, b=2 và c=4, thì ở đây phép tính có thể là '+' hoặc 'x', nhưng nếu thêm 1 dòng nữa bên dưới a=3, b=2 và c=5 chẳng hạn thì giờ kết quả sẽ chính xác hơn 'phép tính' = +.

  • 3.Vì sao các cty công nghệ theo dõi người dùng?. OKe cái ví dụ đánh cầu lông của mình dùng cho dễ minh họa với cuộc sống thôi, chứ về góc độ kỹ thuật thì chả cái platform nào yêu cầu bạn phải "upload" lịch sử hay bảng thống kê để nó "cá nhân hóa" thuật toán cho bạn cả. Mà nó âm thầm theo dõi bạn, ta hay gọi là theo dõi hành vi người dùng, ví dụ như hệ thống đề xuất bài hát đi: nó sẽ có các cột như này: "Thời gian", "Thể loại đang nghe", "Nghệ sĩ"... hệ thống sẽ thu thập lại tất cả thông tin của các cột trên khi bạn click nghe 1 bài hát -> cuối cùng nó sẽ nhận ra vài điều về bạn: "Nếu thời gian là buổi tối thì thằng này khả năng cao sẽ nghe nhạc nhẹ", "Thể loại yêu thích"..., suy ra hành vi của bạn.

  • 4.AI không thể chính xác 100% nó dựa trên xác suất thống kê thôi, trong cuộc sống hàng ngày có hằng trăm thứ ảnh hưởng đến quyết định của bạn chứ ko phải có mấy cái cột trên, và cuộc sống thì có nhiều ngoại lệ mặc dù thỏa mãn các điều kiện để đi chơi nhưng hôm đấy tâm trạng bạn ko tốt chẳng hạn thì kết quả là "KO" chơi cầu lông. Cái số 2 + 3 lý giải các hệ thống đề xuất lớn sẽ thu thập càng nhiều càng tốt, nếu chỉ thu thập mấy thông tin hành vi kia cũng chưa đủ. Hệ thống đề xuất hoạt động tốt nhất là khi nó biết được hành vi của bạn mà ko cần phải đoán, nếu mà nó nghe được bạn nói gì hay nó "hook" được vào tin nhắn của bạn với người khác thì sao nhỉ? Vì sao quảng cáo Facebook nó hiệu quả? Thu thập một đống thông tin kia thì nó cũng ko chắc món đồ bạn đang định mua là gì, nhưng nếu bạn nhắn tin cho ai đó là đang muốn mua một cái iPhone thì bùm ... một đống quảng cáo iPhone đập vào mặt bạn khi bạn mở Facebook ra.