You are on page 1of 19

Nhập môn A.

I
Chi Thanh Nguyen
April 2024

Mục lục
1 Trí tuệ nhân tạo 2

2 Tìm kiếm (Search) 2


2.1 Bài toán tìm kiếm (Search Problems) . . . . . . . . . . . . . . . . . 2
2.2 Giải bài toán tìm kiếm (Solving Search Problems) . . . . . . . . . . 6
2.2.1 Thuật toán tìm kiếm cơ bản . . . . . . . . . . . . . . . . . . 6
2.2.2 Thuật toán tìm kiếm theo độ sâu (Depth-First Search - DFS) 9
2.2.3 Thuật toán tìm kiếm theo chiều rộng (Breadth-First Search
- BFS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2.4 DFS và BFS . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2.5 Cài đặt DFS/BFS . . . . . . . . . . . . . . . . . . . . . . . 18
2.2.5.1 Biểu diễn mê cung trên máy tính . . . . . . . . . . 18

1
Nhập môn A.I Trang 2

1 Trí tuệ nhân tạo


Trí tuệ nhân tạo (A.I) bao gồm một loạt các kỹ thuật xuất hiện dưới dạng
hạnh vi có tri giác của máy tính. Ví dụ, AI được dùng để nhận diện khuôn mặt
để mở khoá điện thoại, chơi cờ vưa thắng nhà vô địch thế giới hay xử lý giọng nói
của bạn như Siri hay Google Assistant.
Sau đây là một số cách giúp hiện thực hoá AI

1. Tìm kiếm (Search): Tìm lời giải cho một bài toán. Ví dụ như tìm con
đường tốt nhất để đi từ điểm xuất phát đến điểm đến hay tìm nước đi tiếp
theo trong một trò chơi.

2. Kiến thức (Knowledge): Biểu diễn thông tin và rút ra suy luận từ nó.

3. Tính không chắc chắn (Uncertainly): Xử lý các sự kiện không chắc chắn
bằng xác xuất.

4. Tối ưu hoá (Optimization): Không chỉ tìm lời giải đúng cho một bài toán
mà là một cách tốt hơn, tốt nhất để giải bài toán.

5. Học (Learning): Cải thiện hiệu suất dựa vào quyền truy cập đến dữ liệu
và trải nghiệm. Ví dụ: email của bạn có thể phân biệt giữa thư rác và thư
không phải thư rác bằng những kinh nghiệm trước đây.

6. Mạng lưới thần kinh (Neural Networks): Một cấu trúc chương trình
lấy ý tưởng từ não người, có thể xử lý những tác vụ một cách hiệu quả.

7. Ngôn ngữ (Language): Xử lý ngôn ngữ tự nhiên, hay ngôn ngữ của con
người.

2 Tìm kiếm (Search)


2.1 Bài toán tìm kiếm (Search Problems)
Bài toán tìm kiếm là một bài toán mà bạn cần tìm ra chuỗi hành động chính
xác sẽ đưa bạn từ trạng thái ban đầu đến mục tiêu.

2 Nguyễn Chí Thanh


Nhập môn A.I Trang 3

Một ví dụ là câu đố 15, khi bạn phải trượt các ô để sắp xếp chúng theo đúng thứ
tự.

Một ví dụ khác là bài toán tìm đường đi qua mê cung. Coi điểm bắt đầu là A và
điểm kết thúc là B, thì bạn cần tìm ra chuỗi hành động chính xác để đi từ trạng
thái ban đầu là A đến mục tiêu là B mà phải tuân theo quy luật là không thể đi
xuyên tường.

Chuyển đến một ví dụ thực tế hơn là chỉ đường lái xe. Google Maps sử dụng một
loại thuật toán tìm kiếm để chỉ đường từ điểm bắt đầu đến điểm đích, tuỳ vào
từng ngã rẽ, tình hình giao thông hay thời gian trong ngày.

3 Nguyễn Chí Thanh


Nhập môn A.I Trang 4

Để tiếp cận đến những bài toá tìm kiếm, đây là một số thuật ngữ cần biết (để
tránh gây ra sai sót khi dịch những thuật ngữ sau đây sẽ là tiếng anh):

• Agent: Một thực thể nhận thức môi trường và hoạt động theo môi trường
đó. Ví dụ trong vấn đề chỉ đường lái xe thì agent sẽ là đại diện của chiếc xe
cần quyết định chuỗi hành động để tới được điểm đến.

• State: Một cấu hình của một agent trong môi trường của nó. Ví dụ trong
câu đố 15, một state là một cách mà các ô được sắp xếp.

• Initial State: Là state khi mà thuật toán sắp xếp bắt đầu. Ví dụ trong bài
toán mê cung thì điểm xuất phát A chính là initial state.

• Actions: Những lựa chọn có thể thực hiện trong một state. Chúng ta có
thể định nghĩa chính xác hơn actions như một hàm. Định nghĩa một hàm
ACT ION S(S) là một hàm nhận vào một state là s, sẽ trả ra một tập hợp
tất cả các hành động có thể được thực hiện ở state s.

Tuy nhiên máy tính sẽ không thể hiểu được những hành động này vì thế
chúng ta cần phải chuyển chúng thành một dạng dữ liệu mà máy tính có thể
hiểu, từ đó chúng ta đến với thuật ngữ tiếp theo.

• Transition Model: Là mô tả của một state mà chúng ta nhận được khi


thực hiện một action trên một state khác. Chúng ta sẽ định nghĩa hàm
RESU LT (s, a) với s là một state và a là một action, hàm này sẽ trả ra state
nhận được khi thực hiện action a lên state s. Ví dụ:

4 Nguyễn Chí Thanh


Nhập môn A.I Trang 5

• State Space: Là tập hợp của các state có thể được đến từ initial state thông
qua bất kỳ chuỗi actions nào. Ví dụ đối với câu đố 15. Gọi state space của
câu đố 15 là S, ta có thể tính |S|.
Dẽ dàng tính được có 16! hoán vị của câu đố 15 nhưng từ một initial state
chúng ta chỉ có thể tới được một nửa số đó. Điều nay xảy ra là do tính chẵn
lẻ. Trong trường hợp này tính chẵn lẻ là hoán vị của các ô trong câu đó có
số lần đảo là chắn hay lẻ. Ví dụ chúng ta chỉ có thể đi từ state S1 đến state
S2 nếu như chúng có cùng tính chẵn lẻ.
16!
Vì vậy |S| = ≈ 1013
2
State space có thể được minh hoạ bằng một đồ thị có hưỡng với mỗi state
là một node và mỗi action là một cạnh.

5 Nguyễn Chí Thanh


Nhập môn A.I Trang 6

• Goal Test: Là một cách kiểm tra xem state hiện tại có phải state mục tiêu
không.
• Path Cost: Là một chi phí bằng số gắn với đường đi được cho. Ví dụ đối
với các ứng dụng chỉ đường nó không chỉ đưa cho chúng ta đường đi mà nó
đưa chúng ta đương đi ngắn nhất, tìm cách nhanh nhất có thể để đến được
goal state. Một ví dụ là đồ thị sau đây:

Mỗi quãng đướng đi từ node này sang node khác sẽ tốn chi phí. Tuy nhiên
đối với trường hợp của câu đố 15 không ảnh hưởng gì khi chúng ta trượt
sang trái hay trượt sang phải, nên chúng ta có thể coi chi phí của mỗi action
là một hằng số (Ví dụ như 1).

2.2 Giải bài toán tìm kiếm (Solving Search Problems)


Trước hết chúng ta có các khải niệm sau:
• Solution: Một chuỗi các action có thể đưa từ initial state đến goal state.
• Optimal Solution: Solution có path cost nhỏ nhất trong tất cả các solution
Đối với bài toán tìm kiếm thì chúng ta không chỉ tìm solution mà cần phải tìm
optimal solution.

2.2.1 Thuật toán tìm kiếm cơ bản


Trong quá trình tìm kiếm chúng ta thường lưu trữ dữ liệu trong một node, một
cấu truc dữ diệu có các thông tin sau:
• State

6 Nguyễn Chí Thanh


Nhập môn A.I Trang 7

• Parent node (node mà tạo ra node này)

• Action (được áp dụng lên parent node để tạo ra node này)

• Path cost từ initial state

Node lưu trữ các thông tin phục vụ cho việc tìm kiếm. State dùng để kiểm tra
liệu đã đến goal state chưa. Nếu như đến goal state thì path cost sẽ giúp tìm ra
optimal solution. Khi đã chon được node thì parent node và action sẽ giúp chúng
ta duyệt ngược lại để tìm ra chuỗi actions.

Tuy nhiên node chỉ là một cấu trúc dữ liệu nên không thể nào tìm kiếm mà chỉ lưu
trữ thông tin. Để thực sự tìm kiếm chúng ta sẽ lưu trữ tất cả các node trong một
cấu trúc dữ liệu duy nhất được gọi là frontier (biên giới), một cơ chế để quản lý
các node. Frontier đại diện cho các node mà chúng ta sắp khám phá và các node
mà chúng ta chưa khám phá. Sử dụng frontier, chúng ta có thể tạo ra thuật toán
tìm kiếm cơ bản như sau:

• Frontier sẽ bắt đầu với việc chứa initial state (do là node gốc nên các giá trị
ngoại trừ state được gán giá trị None)

• Sau đó chúng ta sẽ lặp lại các hành động sau cho đến khi tìm được solution:

– Nếu như frontier rỗng, không có lời giải cho bài toán.
– Xoá một node khỏi frontier.
– Nếu như node vừa xoá chứa goal state, chúng tra trả về solution
– Nếu không, chúng ta xét các node mà có để được tạo ra từ node vừa
xoá, rồi thêm chúng vào frontier.

Ví dụ về thuật toán trên chúng ta có bài toán tìm đường từ A đến E:

7 Nguyễn Chí Thanh


Nhập môn A.I Trang 8

Đầu tiên chúng ta bắt đầu với node A, frontier lúc này sẽ là [A].

Sau đó chúng ta xoá một node khỏi frontier, lúc này do chỉ có node A, nên
chúng ta xoá nó đi. Do A không phai goal state nên chúng ta tiếp tục mở rộng
đến các node con của A là B, rồi thêm B vào frontier. Lúc này frontier là [B].

Do B cũng không phải là goal state, nên chúng ta xoá B khỏi frontier và xét
các node con của B là C và D, tạm thời không quan tâm đến thứ tự chúng ta sẽ
thêm C và D vào frontier và giả sử frontier của chúng ta là: [C, D].

Tiếp theo chúng ta xoá một node khỏi frontier, bỏ qua thứ tự chúng ta chọn
node C. Do C không phải goal state nên chúng ta thêm node con của C vào fron-
tier là E. Frontier lúc này là: [D, E].

Tiếp tục xét D, do không phải goal state nên chúng ta thêm node con của D
là F vào frontier. Frotier lúc này là: [E, F ].

Xét node E, do E là goal state nên chúng ta kết thúc vòng lặp tại đây. Sau
khi duyệ ngược lại từ E ta có mảng thứ tự các node là là [E, C, B, A], do duyệt
ngược lại nên chúng ta phải đảo ngược mảng lại để có được đường đi từ A đến E
là: [A, B, C, E].

Chúng ta xét đến ví dụ sau:

Thực hiện thuật toán frontier bắt đầu với một node A.
Chúng ta xoá A khoải frontier, do A không phải goal state nên chúng ta thêm
node con của A là B vào frontier.

Tiếp tục xoá B, do B vẫn không phải goal state nên chúng ta thêm tất cả

8 Nguyễn Chí Thanh


Nhập môn A.I Trang 9

node mà có thể đến từ B vào frontier. Do lúc này B được nối ngược lại với A, nên
frontier lúc này sẽ là: [A, C, D].

Xoá node A khỏi frontier, nhân thầy đây tiếp tục là bước ban đầu, nên nếu
tiếp tục sẽ tạo ra vòng lặp vô tân. Vì vậy chúng ta không thể áp dụng thuật toán
trên với mọi trường hợp. ⇒ Chúng ta cần cải tiến thuật toán.

2.2.2 Thuật toán tìm kiếm theo độ sâu (Depth-First Search - DFS)
Nhận thấy vấn đề của thuật toán vừa rồi là có thể quay lại những node đã
được khám phá.
Chúng ta sẽ lưu trữ tất cả những node đã khám phá vào một tập hợp gọi là explored
set. Trong quá trình mở rộng node chúng ta chỉ thêm vào frontier các node chưa
có trong explored set.
Từ đó chúng ta có thuật toán sau:

• Frontier sẽ bắt đầu với việc chứa initial state (do là node gốc nên các giá trị
ngoại trừ state được gán giá trị None)

• Explored set sẽ bắt đầu là một tập hợp rỗng.

• Sau đó chúng ta sẽ lặp lại các hành động sau cho đến khi tìm được solution:

– Nếu như frontier rỗng, không có lời giải cho bài toán.
– Xoá một node khỏi frontier.
– Nếu như node vừa xoá chứa goal state, chúng tra trả về solution
– Thêm node vừa xoá vào explored set.
– Nếu không, chúng ta xét các node mà có để được tạo ra từ node vừa
xoá, rồi thêm chúng vào frontier nếu như chúng chưa có trong frontier
và explored set.

Tuy nhiên cách chúng ta xoá node khỏi frontier vẫn đang là chọn ngẫu nhiên,
chúng ta cần một thứ tự để xoá phần tử. Để làm như vậy chúng ta sử dụng một
cấu trúc dữ liệu là stack (ngăn xếp) - một kiểu dữ liệu hoạt động theo cấu trúc
LIFO (Last In - First Out). Stack hoạt động giống một mảng, phần từ cuối cùng
được gọi là đỉnh stack. Một stack có các thao tác như sau:

• push(): thêm phần tử vào cuối danh sách.

• pop(): xoá phần từ đang ở đỉnh stack.

• top(): trả về phần tử ở đỉnh stack.

Chúng ta sẽ cho frontier hoạt động theo cấu trúc của stack. Mỗi khi thêm/xoá
node, chúng ta sẽ sử dụng các thao tác push và pop tương ứng.

9 Nguyễn Chí Thanh


Nhập môn A.I Trang 10

Chúng ta sẽ áp dụng thuật toán mới với bài toán vừa rồi:

Khởi đầu với frontier và explored set:

- Frontier = [A].

- Explored Set = {}.

Xoá A khỏi frontier do A không phải goal state, chúng ta thêm B vào frontier.
Để đánh dấu đã khám phá A, chúng ta thêm A vào explored set:

- Frontier = [B].

- Explored Set = {A}.

Xoá A khỏi frontier do A không phải goal state, chúng ta thêm các node có
thể đến được B vào frontier là A, C, D, tuy nhiên do A đã nằm trong explored set
nên chúng ta không thêm vào. Để đánh dấu đã khám phá B, chúng ta thêm B
vào explored set:

- Frontier = [C, D].

- Explored Set = {A, B}.

Lúc này frontỉer có hai phần tử áp dụng theo cấu trúc của stack chúng ta sẽ
loại bỏ D, do D không phải goal state, nên chúng ta sẽ thêm F vào frontier đồng
thời thêm D vào explored set:

- Frontier = [C, F ].

- Explored Set = {A, B, D}.

Tiếp tục xoá node ở đỉnh stack, chúng ta xoá F khỏi frontier. Do không có
node nào đến được F nên chúng ta thêm F vào explored set:

10 Nguyễn Chí Thanh


Nhập môn A.I Trang 11

- Frontier = [C].

- Explored Set = {A, B, D, F }.

Chúng ta xoá C khỏi frontier. Do không phải goal state nên chúng ta thêm E
vào frontier và thêm C vào explored set:

- Frontier = [E].

- Explored Set = {A, B, C, D, F }.

Xoá E khỏi frontier, do E là goal state nên chúng ta trả về solution về kết thúc
vòng lặp.

Chúng ta gọi phiên bản này của thuật đoán là thuật toán tìm kiếm theo chiều sâu
(Depth-First Search), viết tắt là DFS. Một thuật toán luôn luôn mở rộng node sâu
nhất ở frontier.

2.2.3 Thuật toán tìm kiếm theo chiều rộng (Breadth-First Search -
BFS)
DFS không phải lựa chọn duy nhất để tìm kiếm chúng ta có một thuật toán
khác tương tự là BFS. Khác với DFS luôn luôn mở rộng node sâu nhất ở frontier,
BFS luôn luôn mở rộng node nông nhất ở frontier.
Để sử dụng thuật toán này chúng ta đơn giản chỉ cần sửa đổi một chút ở DFS,
thay vì sử dụng stack để biểu diễn frontier chúng ta sử dụng một cấu trúc dữ liệu
khác là queue (hàng đợi).
Queue là một cấu trúc dữ liệu hoạt động theo cấu trúc FIFO (First In - First
Out), các thao tác cơ bản trên queue là:

• push(): thêm phần tử vào cuối danh sách.

• pop(): xoá phần từ đang ở đầu danh sách.

• front(): trả về phần tử ở đầu danh sách.

• back(): trả về phần tử ở cuối danh sách.

Áp dụng BFS với bài toán trên ta có:

11 Nguyễn Chí Thanh


Nhập môn A.I Trang 12

Khởi đầu với frontier và explored set:

- Frontier = [A].

- Explored Set = {}.

Tiếp tục xoá A và thêm B vào frontier :

- Frontier = [B].

- Explored Set = {A}.

Tiếp tục thực hiện ta xoá B và thêm C và D vào frontier :

- Frontier = [C, D].

- Explored Set = {A, B}.

Đây là lúc mà thuật toán này trở nên khác biệt so với DFS. Sử dụng thao tác
pop của queue, chúng ta xoá C khỏi frontier, sau đó thêm E vào cuối frontier :

- Frontier = [D, E].

- Explored Set = {A, B, C}.

Tiếp tục áp dụng thao tác trên, chúng ta xoá D khỏi frontier, sau đố thêm F
vào:

- Frontier = [E, F ].

- Explored Set = {A, B, C, D}.

Xoá E khỏi frontier, nhận thầy E là goal state, chúng ta trả về solution và
dừng vòng lặp.

12 Nguyễn Chí Thanh


Nhập môn A.I Trang 13

2.2.4 DFS và BFS

Chúng ta sẽ biểu diễn DFS trên mê cung này, đi từ A đến B.


Bước đầu chúng ta đi đến ngã ba.

Ở đây chúng ta sẽ khám phá theo từng hướng, giả sử khám phá hướng bên trái
trước. Bước đầu chúng ta đi đến ngã ba.

Tiếp tục làm giống như trước chúng ta khám phá từng bên:

13 Nguyễn Chí Thanh


Nhập môn A.I Trang 14

Nhận thấy khi đi về đo không thể đến đích chúng ta chuyển hướng sang bên
phải.

Tiếp tục như vậy cho đến hết mê cung.

14 Nguyễn Chí Thanh


Nhập môn A.I Trang 15

Nhận thầy đối với cách này chúng ta chó thể tìm được optimal solution, tuy
nhiên chúng ta thử xét ví dụ sau.

Dễ dàng nhận thấy có hai cách giải:

Cách bên phải là optimal solution, tuy nhiện nêu may mắn chúng ta có thể có
được optimal solution còn nếu không thì chúng ta chỉ có thể có được solution.
Qua đó chúng ta có được ưu/nhược điểm của DFS:

• Ưu điểm

– Trong trường hợp tốt nhất DFS là nhanh nhất. Nếu như đủ may mắn
thì thuật toán này liên tục chon đường đi ngắn nhất và đến đích.

• Nhược điểm

– Có thể cho ra solution không được optimal


– Trong trường hợp xấu nhất thì thuật toán này sẽ duyệt qua mọi đường
đi trước khi đến đích. Lúc này thì thuật toán này là chạy chậm nhất.

15 Nguyễn Chí Thanh


Nhập môn A.I Trang 16

Chúng ta thử áp dụng BFS cho mê cung vừa rồi.


Khác với DFS, BFS sẽ cùng lúc khám phá mọi con đường. Sau đây là một quy
trình BFS đối với mê cung trên

Do xét mọi con đường nên BFS có thể cho ra optimal solution.

16 Nguyễn Chí Thanh


Nhập môn A.I Trang 17

Chúng ta thử dùng BFS với mê cung ban đầu:

Ban đầu khi chưa có ngã rẽ BFS hoạt động giống DFS.

Đây là lúc xảy ra sự khác biệt khi BFS xet mọi con đường thay vì tường con
đường như DFS.

17 Nguyễn Chí Thanh


Nhập môn A.I Trang 18

Cuối cùng chúng ta tới được đích:

Qua đó chúng ta có được ưu/nhược điểm của BFS:

• Ưu điểm

– Thuật toán này luôn luôn tìm được optimal solution.

• Nhược điểm

– Thuật toán nay hầu như sẽ mất nhiều thời gian hơn thời gian chạy tối
thiểu.

2.2.5 Cài đặt DFS/BFS


Chúng ta sẽ cài đặt một chương trình sử dụng BFS và DFS để đi từ điểm A
đến B trong mê cung với tính năng năng như sau:

• Cho người dùng nhập một mê cung từ một file

• Cho người dùng chọn DFS hoặc BFS để tìm đường trong mê cung

• Xuất ra lời giải và số ô đã khám phá

2.2.5.1 Biểu diễn mê cung trên máy tính


Chúng ta sử dụng ra một class mê cung trung đó lựa chọn khởi tạo là đọc từ file.
Ở đây tôi quy ước ký tự ’#’ là biểu diễn tường, ký tự ’ ’ (space) là biểu diễn ô
trống, ký tự ’A’ là biểu diễn điểm bắt đầu và ký tự ’B’ biểu diễn đích đến. Từ đó
ta có đoạn code sau:

class Maze:
def __init__(self, filename):
with open(filename) as f:
contents = f.read()

if contents.count('A') != 1:
raise Exception(\'The maze must contains exactly one start point')
if contents.count('B') != 1:

18 Nguyễn Chí Thanh


Nhập môn A.I Trang 19

raise Exception('The maze must contains exactly one goal point')


if any(c not in ['\n', ' ', '#', 'A', 'B'] for c in contents):
raise Exception('Invalid Input')

contents = contents.strip().splitlines()
self.row = len(contents)
self.col = max([len(i) for i in contents])
self.wall = []
self.solution = None
self.explored_set = None
for i in range(self.row):
t = []
for j in range(self.col):
try:
if contents[i][j] == ' ': t.append(True)
elif contents[i][j] == 'A':
self.start = (i, j)
t.append(True)
elif contents[i][j] == 'B':
self.goal = (i, j)
t.append(True)
else: t.append(False)
except IndexError:
t.append(True)
self.wall.append(t)

19 Nguyễn Chí Thanh

You might also like