1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Tiểu luận xây dựng mô hình cnn cho phân lớp nhị phân sử dụng julia học phần phân tích dữ liệu lớn

50 4 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Xây Dựng Mô Hình CNN Cho Phân Lớp Nhị Phân Sử Dụng Julia
Tác giả Nguyễn Quốc Khánh
Người hướng dẫn TS.Võ Phương Bình
Trường học Đại học Đà Lạt
Chuyên ngành Toán Tin học
Thể loại tiểu luận
Năm xuất bản 2024
Thành phố Đà Lạt
Định dạng
Số trang 50
Dung lượng 2,03 MB

Cấu trúc

  • 2.1 Cài đặt Core Julia và các thư viện cần thiết (12)
  • 2.2 Biến số, toán tử, kiểu dữ liệu (13)
  • 2.3 Cấu trúc điều khiển (15)
  • 2.4 Cấu trúc dữ liệu (18)
  • 2.5 Hàm trong Julia (21)
  • 2.6 Giới thiệu thư viện Flux (23)
  • 3.1 Tích chập (Convolution) (26)
    • 3.1.1 Công thức (26)
    • 3.1.2 Ví dụ minh họa (26)
  • 3.2 Lớp kích hoạt (Activation Layer) (27)
    • 3.2.1 Các hàm kích hoạt phổ biến (27)
    • 3.2.2 Ví dụ minh họa (27)
  • 3.3 Lớp gộp (Pooling Layer) (28)
    • 3.3.1 Các loại gộp (28)
    • 3.3.2 Ví dụ minh họa (28)
  • 3.4 Lớp Fully Connected (FC) (28)
    • 3.4.1 Công thức (28)
    • 3.4.2 Ví dụ minh họa (29)
  • 3.5 Lớp Batch Normalization (BN) (29)
    • 3.5.1 Công thức (29)
    • 3.5.2 Ví dụ minh họa (29)
  • 3.6 Lan truyền tiến (Forward Propagation) (29)
    • 3.6.1 Ví dụ (30)
  • 3.7 Lan truyền ngược (Backward Propagation) (31)
    • 3.7.1 Ví dụ (31)
  • 3.8 Các thuật toán tối ưu trong CNN (32)
    • 3.8.1 Gradient Descent (GD) (32)
    • 3.8.2 Stochastic Gradient Descent (SGD) (33)
    • 3.8.3 Momentum (33)
    • 3.8.4 AdaGrad (34)
    • 3.8.5 RMSprop (Root Mean Square Propagation) (34)
    • 3.8.6 Adam (Adaptive Moment Estimation) (35)
    • 3.8.7 Nadam (Nesterov-accelerated Adaptive Moment Estimation) (35)
  • 4.1 Tạo Dataset (Hàm TạoDataset) (42)
  • 4.2 Chuẩn Bị Dữ Liệu (Train và Test) (43)
  • 4.3 Xây Dựng Mô Hình CNN (43)
  • 4.4 Hàm Mất Mát (Loss Function) (43)
  • 4.5 Tạo DataLoader Thủ Công (44)
  • 4.6 Huấn Luyện Mô Hình (44)
  • 4.7 Đánh Giá Mô Hình (44)
  • 4.8 Confusion Matrix (44)
  • 4.9 Tính Các Chỉ Số Đánh Giá (44)
  • 4.10 Vẽ Biểu Đồ và Lưu Kết Quả (45)
  • 1.2 Ví dụ về hình ảnh lá cây từ bộ dữ liệu PlantVillage, đại diện cho mỗi cặp cây trồng - bệnh được sử dụng. (1) Apple Scab, Venturia inaequalis (2) (0)
  • 1.3 Sự phân bố của các loài và bệnh trong bộ dữ liệu [1] (0)
  • 1.4 Số lượng ảnh trong một số thư mục của bộ dữ liệu, trong có thư mục lá đào khỏe gồm 360 ảnh và thư mục lá đào có bệnh gồm 997 ảnh (0)
  • 1.5 Bốn lá đào khỏe mạnh (0)
  • 1.6 Bốn lá đào có bệnh (0)
  • 2.1 Toán tử số học trong Julia (0)
  • 2.2 Toán tử so sánh trong Julia (0)
  • 2.3 Toán tử logic trong Julia (0)
  • 2.4 Toán tử ghép gán trong Julia (0)

Nội dung

Mở đầuTrong tiểu luận này tôi lựa chọn một chủ đề quen thuộc và quan trọng trong học sâu là phân loại, cụ thể là phân loại nhị phân có giám sát, tiến hành xây dựng mô hình mạng nơ ron ho

Cài đặt Core Julia và các thư viện cần thiết

⋆ Truy cập trang chính thức: https://julialang.org/downloads/

⋆ Tải phiên bản Julia phù hợp với hệ điều hành của bạn (Windows, macOS, hoặc Linux).

⋆ Cài đặt Julia theo hướng dẫn cụ thể cho hệ điều hành của bạn:

⋆ Windows: Chạy file exe và làm theo hướng dẫn

⋆ macOS/Linux: Giải nén file tải về hoặc sử dụng trình quản lý gói.

⋆ Trong lúc cài đặt Julia, chọn tùy chọn Add Julia to PATH (trên Windows).

• Cài đặt Visual Studio Code

⋆ Truy cậphttps://code.visualstudio.com/và tải bản cài đặt cho hệ điều hành của bạn.

⋆ Cài đặt VS Code theo hướng dẫn.

• Cài đặt Extension Julia cho VS Code

• Tìm extension tên Julia (được phát triển bởi julialang).

• Nhấn Install để cài đặt.

• Cài đặt các gói cần thiết

⋆ Để cài các gói hỗ trợ, gõ các lệnh sau trên Terminal: julia> using Pkg julia> Pkg.add("Tên gói")

Biến số, toán tử, kiểu dữ liệu

Biến số trong Julia được dùng để lưu trữ giá trị Dưới đây là cách khai báo:

# Khai báo biến x = 10 # Biến số nguyên y = 3.14 # Biến số thực z = "Hello" # Chuỗi ký tự is_active = true # Biến Boolean a, b, c = 1, 2, 3 # Gán giá trị cho nhiều biến

Hằng số được khai báo với từ khóa const: const PI = 3.14159

Julia hỗ trợ nhiều loại toán tử:

Bảng 2.1: Toán tử số học trong Julia

Toán tử Ý nghĩa Ví dụ

Bảng 2.2: Toán tử so sánh trong Julia

Toán tử Ý nghĩa Ví dụ

= 3 → true

Bảng 2.3: Toán tử logic trong Julia

Toán tử Ý nghĩa Ví dụ

|| Phép hoă (OR) true || false →true

|| Phép hoă (OR) true || false →true

! Phủ định (NOT) !true → false

Bảng 2.4: Toán tử ghép gán trong Julia

Toán tử Ý nghĩa Ví dụ += Cộng và gán x += 1 (x = x + 1) -= Trừ và gán x -= 1 (x = x - 1)

*= Nhân và gán x *= 2 (x = x * 2) /= Chia và gán x /= 2 (x = x / 2)

3 Kiểu dữ liệu (Data Types)

Julia hỗ trợ nhiều kiểu dữ liệu cơ bản và nâng cao:

Kiểu dữ liệu cơ bản:

• Bool: Boolean (vd: true,false).

• String: Chuỗi ký tự (vd: "hello").

Kiểu dữ liệu phức tạp:

• Tuple: Bộ giá trị bất biến (vd: (1, "hello", true)).

• Dict: Từ điển (vd: Dict("a" => 1, "b" => 2)).

Kiểm tra và chuyển đổi kiểu dữ liệu:

# Kiểm tra kiểu dữ liệu x = 10 println(typeof(x)) # Int64

# Ép kiểu y = Float64(x) # Chuyển x thành số thực println(y) # Kết quả: 10.0

Cấu trúc điều khiển

Trong Julia, cấu trúc điều khiển cho phép kiểm tra các điều kiện và lặp lại đoạn mã dựa trên các điều kiện đó Các cấu trúc điều khiển chính bao gồm if, else, for, while và try-catch, giúp lập trình viên điều khiển luồng thực thi của chương trình một cách linh hoạt và hiệu quả.

Câu lệnh if trong Julia cho phép bạn kiểm tra một điều kiện và thực thi các đoạn mã dựa trên điều kiện đó. if điều_kiện

# Các câu lệnh sẽ được thực thi nếu điều_kiện là true elseif điều_kiện_khác

# Các câu lệnh sẽ được thực thi nếu điều_kiện_khác là true else

# Các câu lệnh sẽ được thực thi nếu không có điều kiện nào đúng end

Ví dụ: x = 10 if x > 5 println("x lớn hơn 5") elseif x == 5 println("x bằng 5") else println("x nhỏ hơn 5") end

Câu lệnh fortrong Julia được sử dụng để lặp qua các phần tử trong một dãy giá trị. for biến in dãy

# Các câu lệnh sẽ được thực thi cho mỗi phần tử trong dãy end

Ví dụ: for i in 1:5 println(i) end

Câu lệnh while cho phép bạn lặp lại các câu lệnh trong khi điều kiện còn đúng. while điều_kiện

# Các câu lệnh sẽ được thực thi miễn là điều_kiện là true end

Ví dụ: x = 1 while x 1, "banana" => 2)

Ví dụ: d = Dict("apple" => 1, "banana" => 2) println(d["apple"]) # Truy cập giá trị của "apple": 1

Set là một cấu trúc dữ liệu lưu trữ một tập hợp các phần tử duy nhất, không cho phép các phần tử trùng lặp.

Cú pháp khai báo: s = Set([1, 2, 3, 4])

Ví dụ: s = Set([1, 2, 3, 4]) println(3 in s) # Kiểm tra xem 3 có trong set không: true

String trong Julia là một chuỗi các ký tự Julia cung cấp nhiều chức năng mạnh mẽ để xử lý chuỗi ký tự.

Cú pháp khai báo: str = "Hello, World!"

Ví dụ: str = "Hello, World!" println(str[1]) # Truy cập ký tự đầu tiên trong chuỗi: "H" println("Hello" * " " * "World") # Nối chuỗi

Struct trong Julia cho phép định nghĩa các kiểu dữ liệu phức tạp với các trường dữ liệu có kiểu dữ liệu khác nhau.

Cú pháp khai báo: struct Person name::String age::Int end

Ví dụ: p = Person("John", 30) println(p.name) # Truy cập trường "name" trong struct: John

7 Mảng có kiểu dữ liệu tùy chỉnh

Julia cho phép bạn tạo các mảng chứa các kiểu dữ liệu tùy chỉnh được định nghĩa bởi người dùng, như cấu trúc (struct).

Ví dụ: struct Point x::Int y::Int end points = [Point(1, 2), Point(3, 4), Point(5, 6)] println(points[2].x) # Truy cập thuộc tính x của phần tử thứ 2: 3

8 Cấu trúc dữ liệu khác

Julia cung cấp các cấu trúc dữ liệu mạnh mẽ khác như:

• Range: Dùng để tạo các dãy giá trị liên tiếp (ví dụ: 1:5tạo dãy từ 1 đến 5).

Trong ngôn ngữ lập trình Julia, mặc dù không có kiểu dữ liệu Queue hay Stack được tích hợp sẵn, nhưng bạn có thể dễ dàng tạo ra chúng bằng cách sử dụng các hàm push! và pop! trên mảng.

• ArrayViews: Dùng để tạo các views không thay đổi từ một mảng ban đầu mà không sao chép dữ liệu.

Hàm trong Julia

Trong ngôn ngữ lập trình Julia, hàm là một khối mã được thiết kế để thực hiện nhiệm vụ cụ thể Hàm có khả năng nhận đối số, thực hiện các phép toán hoặc xử lý dữ liệu và trả về kết quả Bài viết này sẽ hướng dẫn bạn cách định nghĩa và sử dụng hàm trong Julia.

1 Định nghĩa hàm đơn giản

Để định nghĩa một hàm trong Julia, bạn cần sử dụng từ khóa "function", tiếp theo là tên hàm cùng với các tham số và phần thân hàm Cuối cùng, hãy sử dụng từ khóa "end" để kết thúc định nghĩa hàm.

Cú pháp: function ten_ham(tham_so1, tham_so2)

# Thân hàm return gia_tri end

Ví dụ: function add(a, b) return a + b end result = add(2, 3) println(result) # In ra 5

2 Hàm không trả về giá trị

Nếu hàm không có từ khóa return, nó sẽ tự động trả về kết quả cuối cùng trong thân hàm Ví dụ:

Ví dụ: function print_sum(a, b) println(a + b) end print_sum(5, 7) # In ra 12

3 Hàm với tham số mặc định

Julia cho phép gán giá trị mặc định cho các tham số trong hàm, giúp sử dụng hàm dễ dàng hơn Khi bạn gọi hàm mà không cung cấp đối số cho tham số đó, giá trị mặc định sẽ tự động được áp dụng.

Ví dụ: function greet(name="Guest") println("Hello, $name!") end greet() # In ra "Hello, Guest!" greet("John") # In ra "Hello, John!"

4 Hàm vô danh (Anonymous Functions)

Hàm vô danh, hay còn gọi là hàm lambda, là những hàm không có tên, thường được sử dụng để thực hiện các tác vụ tạm thời Chúng rất hữu ích trong các phép toán như map và filter, giúp tối ưu hóa quy trình xử lý dữ liệu.

Cú pháp: f = x -> x^2 println(f(3)) # In ra 9

5 Hàm với nhiều giá trị trả về

Julia hỗ trợ việc trả về nhiều giá trị từ hàm thông qua Tuple, cho phép bạn sử dụng nhiều giá trị trả về trong một lần gọi hàm.

To find the minimum and maximum values in an array, you can use the function `get_min_max(arr)` which returns both the minimum and maximum values For example, given the array `arr = [1, 5, 3, 9, 2]`, calling `get_min_max(arr)` will yield `min_val` as 1 and `max_val` as 9 The output will display "Min: 1, Max: 9".

6 Hàm với các tham số kiểu dữ liệu tùy chỉnh

Julia cho phép bạn định nghĩa các hàm với tham số có kiểu dữ liệu tùy chỉnh, chẳng hạn như Struct.

Ví dụ: struct Person name::String age::Int end function greet(person::Person) str = "Hello, my name is $(person.name)" \

"and I am $(person.age) years old." println(str) end p = Person("Alice", 25) greet(p) # In ra "Hello, my name is Alice and I am 25 years old."

Hàm đệ quy là hàm gọi chính nó trong thân hàm Điều này hữu ích khi giải quyết các bài toán phân chia và trị.

Ví dụ: function factorial(n) if n == 0 return 1 else return n * factorial(n - 1) end end println(factorial(5)) # In ra 120

Giới thiệu thư viện Flux

Flux.jl là thư viện nổi bật trong Julia dành cho việc xây dựng và huấn luyện mô hình học sâu Với tính năng dễ sử dụng, linh hoạt và hiệu quả, Flux phù hợp cho cả những người mới bắt đầu và các nhà nghiên cứu trong lĩnh vực học máy và trí tuệ nhân tạo.

1 Cài đặt Flux.jl Để cài đặt Flux.jl trong Julia, bạn có thể sử dụng Pkgnhư sau: using Pkg

2 Các tính năng chính của Flux.jl

Flux.jl cho phép người dùng định nghĩa các mô hình học sâu một cách dễ dàng thông qua các hàm và cấu trúc rõ ràng Nó bao gồm các thành phần như lớp mạng nơ-ron, hàm kích hoạt, và các phương pháp tối ưu hóa, giúp tối ưu hóa quy trình phát triển mô hình.

• Tối ưu hóa linh hoạt: Flux hỗ trợ nhiều thuật toán tối ưu hóa như Stochastic Gradient Descent (SGD), Adam.

• Hỗ trợ GPU: Flux có thể sử dụng GPU để tăng tốc huấn luyện mô hình.

• Dễ dàng mở rộng và tùy biến: Flux cho phép tạo các lớp và hàm tùy chỉnh.

3 Cấu trúc cơ bản của Flux.jl

Flux.jl là một thư viện mạnh mẽ cho việc định nghĩa mô hình học sâu, cung cấp các lớp mạng nơ-ron, hàm kích hoạt và thuật toán tối ưu hóa Ngoài ra, Flux.jl còn trang bị các công cụ hỗ trợ cho quá trình huấn luyện và đánh giá mô hình, giúp người dùng dễ dàng phát triển và triển khai các ứng dụng học máy hiệu quả Dưới đây là bảng mô tả các thành phần chính của Flux.jl.

Thành phần Mô tả Ví dụ

Chain Container chứa các lớp mạng nơ- ron liên tiếp Giúp xây dựng mô hình học sâu một cách dễ dàng. model = Chain(Dense(2, 5, relu), Dense(5, 1))

Dense Lớp fully connected (mạng nơ-ron dày đặc), được sử dụng để kết nối các nơ-ron giữa các lớp.

Conv Lớp tích chập (convolutional layer) sử dụng trong mạng nơ-ron tích chập (CNN).

LSTM Lớp Long Short-Term Memory

(LSTM) sử dụng trong các mô hình học sâu tuần tự.

GRU Lớp Gated Recurrent Unit

(GRU), một loại mô hình tuần tự.

GRU(10) relu Hàm kích hoạt Rectified Linear

Unit, chuyển giá trị âm về 0. relu(x)

Hàm kích hoạt sigmoid chuyển giá trị về phạm vi (0, 1) và được biểu diễn bằng sigmoid(x) Hàm tangens hyperbolic (tanh) chuyển giá trị về phạm vi (-1, 1) với công thức tanh(x) Hàm softmax chuyển đổi giá trị thành xác suất thông qua softmax(x) Cuối cùng, hàm mất mát Mean Squared Error (MSE) đo độ lệch giữa giá trị dự đoán và giá trị thực, được tính bằng mse.

Flux.mse(model(x), y) crossentropy Hàm mất mát Cross Entropy, thường dùng trong các bài toán phân loại.

Flux.crossentropy(model(x), y) adam Thuật toán tối ưu hóa Adam, kết hợp gradient descent và momen- tums. optimizer = Adam(0.001) sgd Thuật toán tối ưu hóa Stochastic

Descent Thuật toán gradient descent cơ bản. optimizer = Descent(0.01) train! Hàm huấn luyện mô hình, cập nhật tham số theo gradient de- scent.

Hàm `Flux.train!(loss, params(model), [(X, y)], optimizer)` được sử dụng để thực hiện quá trình huấn luyện mô hình, trong đó `backprop!` tính toán gradient cho các tham số của mô hình Hàm `backprop!(loss, params(model))` giúp truy xuất các tham số của mô hình, từ đó cập nhật trọng số trong quá trình huấn luyện.

Zygote Thư viện tính toán đạo hàm tự động giúp Flux thực hiện back- propagation và cập nhật các trọng số. using Zygote

GPU Hỗ trợ tính toán trên GPU giúp tăng tốc quá trình huấn luyện, yêu cầu cài đặt CUDA.jl.

Cơ sở lý thuyết mạng CNN

Tích chập (Convolution)

Công thức

• I: Ma trận đầu vào (input image).

• S(i, j): Giá trị đầu ra tại vị trí(i, j) trong feature map.

Ví dụ minh họa

Cho một ảnh grayscaleI kích thước 3×3:

Kết quả feature map đầu ra là:

Lớp kích hoạt (Activation Layer)

Các hàm kích hoạt phổ biến

1 ReLU (Rectified Linear Unit): f(x) = max(0, x)

Ví dụ minh họa

Cho feature map đầu ra từ lớp tích chập:

Lớp gộp (Pooling Layer)

Các loại gộp

• Max Pooling: Lấy giá trị lớn nhất trong một vùng.

• Average Pooling: Tính giá trị trung bình trong một vùng.

Ví dụ minh họa

 Áp dụng max pooling 2×2với stride = 1:

Lớp Fully Connected (FC)

Công thức

Ví dụ minh họa

Cho đầu vào x= [1,0.5], trọng số và bias:

Lớp Batch Normalization (BN)

Công thức

• à, σ 2 : Trung bỡnh và phương sai của batch.

• ϵ: Hằng số nhỏ để tránh chia cho 0.

Ví dụ minh họa

Lan truyền tiến (Forward Propagation)

Ví dụ

Giả sử chúng ta có một CNN với 2 lớp chính: một lớp convolution và một lớp fully connected.

Bước 1: Dữ liệu đầu vào - Dữ liệu đầu vào là một ảnh xám 4x4 pixel, mỗi pixel có giá trị từ 0 đến 1.

Bước 2: Áp dụng Convolution - Giả sử chúng ta có một bộ lọc (kernel) 2x2 với giá trị:

Bộ lọc sẽ được áp dụng cho ảnh đầu vào thông qua phép toán convolution, trong đó chúng ta tính toán giá trị tại từng vùng phủ của bộ lọc trên ảnh.

- Vùng phủ đầu tiên của bộ lọc sẽ nằm trên góc trên bên trái của ảnh, giá trị tính toán sẽ là:

(0×1) + (0×0) + (0×0) + (1× −1) =−1 Sau khi áp dụng bộ lọc qua các vùng của ảnh, chúng ta thu được một ma trận đầu ra:

Bước 3: Áp dụng Hàm Kích Hoạt - Sau khi thực hiện phép toán convolution, chúng ta sử dụng hàm kích hoạt, như hàm ReLU, để chuyển đổi tất cả các giá trị âm thành 0.

Step 4: Fully Connected Layer - The values from the convolutional layer are fed into the fully connected layer to produce the final output For instance, the fully connected layer may have a simple weight.

Tính toán đầu ra từ lớp fully connected sẽ là: y=W T A+b= 1×0 + 1×1 + 1×1 + 0 = 2Kết quả: Đầu ra của mạng lày= 2.

Lan truyền ngược (Backward Propagation)

Ví dụ

Trong quá trình huấn luyện mô hình, mục tiêu là đạt được giá trị đầu ra mong muốn là true = 1, chẳng hạn như trong bài toán phân loại ảnh Lan truyền ngược được sử dụng để điều chỉnh các trọng số nhằm giảm thiểu sai số giữa giá trị dự đoán (y pred) và giá trị thực tế (y true).

Bước 1: Tính Toán Lỗi (Loss)- Chúng ta sử dụng hàm mất mát bình phương sai số (mean squared error):

Với y pred = 2 và y true = 1, ta có:

2 Bước 2: Tính Gradient của Lỗi- Gradient của hàm mất mát đối với đầu ra y pred là:

Step 3: Update Weights in the Fully Connected Layer - Assuming the fully connected layer has weights W and biases b, we need to calculate the gradient of the loss function with respect to these weights Update the weights using gradient descent with a learning rate of η = 0.1.

Trong đó ∂W ∂L là đạo hàm của hàm mất mát theo trọng số Tính toán tương tự sẽ được thực hiện cho các lớp convolutional.

Bước 4: Cập nhật trọng số và độ lệch - Sau khi tính toán gradient, trọng số trong các lớp convolutional và fully connected sẽ được điều chỉnh dựa trên gradient này Việc cập nhật trọng số nhằm mục tiêu giảm thiểu hàm mất mát trong các lần huấn luyện tiếp theo.

Các thuật toán tối ưu trong CNN

Gradient Descent (GD)

Gradient Descent (GD) là thuật toán tối ưu quan trọng, thường được áp dụng trong việc huấn luyện mạng nơ-ron, đặc biệt là CNN Mục tiêu chính của GD là xác định các trọng số tối ưu nhằm giảm thiểu giá trị hàm mất mát (loss function).

Công thức cập nhật trọng số: w=w−η∇ w L(w)

• η là tốc độ học (learning rate).

• ∇ w L(w) là gradient của hàm mất mátL(w) theo trọng sốw.

GD tính toán gradient của hàm mất mát và cập nhật trọng số theo hướng ngược lại với gradient, nhằm giảm thiểu giá trị của hàm mất mát.

• Các biến thể của Gradient Descent

⋆ Batch Gradient Descent: Cập nhật trọng số dựa trên toàn bộ tập huấn luyện. Phù hợp với các bộ dữ liệu nhỏ.

Stochastic Gradient Descent (SGD) là phương pháp cập nhật trọng số sau mỗi mẫu huấn luyện, giúp tăng tốc quá trình học và tối ưu hóa hiệu quả khi làm việc với bộ dữ liệu lớn.

⋆ Mini-batch Gradient Descent: Kết hợp giữa batch và SGD, cập nhật trọng số sau mỗi nhóm mẫu (mini-batch), giúp tận dụng ưu điểm của cả hai.

Stochastic Gradient Descent (SGD)

Stochastic Gradient Descent (SGD) là một phiên bản cải tiến của Gradient Descent, cho phép cập nhật trọng số sau mỗi mẫu huấn luyện thay vì toàn bộ tập huấn luyện Phương pháp này giúp giảm độ trễ và tăng tốc độ quá trình huấn luyện, mang lại hiệu quả cao hơn trong việc tối ưu hóa mô hình.

• Tính toán nhanh, đặc biệt khi làm việc với bộ dữ liệu lớn.

• Có khả năng thoát khỏi các điểm tối ưu cục bộ nhờ sự "ngẫu nhiên" trong cập nhật trọng số.

• Quá trình tối ưu không ổn định, có thể dao động quanh giá trị tối ưu thay vì hội tụ chính xác.

Momentum

Momentum là một phương pháp cải tiến của SGD, giúp tăng tốc độ hội tụ và làm mượt quá trình tối ưu hóa Thay vì chỉ dựa vào gradient của hàm mất mát tại từng bước, Momentum sử dụng thông tin từ các bước trước để xác định hướng cập nhật trọng số Công thức cập nhật trọng số với Momentum được thể hiện như sau: v t =βv t−1 + (1−β)∇ w L(w), w = w − ηvt.

• v t là vận tốc (momentum) tại bướct.

• β là hệ số momentum (thường được chọn là giá trị gần 1, ví dụ 0.9).

Momentum giúp giảm độ dao động và cải thiện tốc độ hội tụ của quá trình huấn luyện,đặc biệt khi hàm mất mát có độ dốc không đều.

AdaGrad

AdaGrad (Thuật toán Gradient Điều chỉnh) là một phương pháp tối ưu hóa tự động điều chỉnh tốc độ học cho từng trọng số trong mạng Thay vì áp dụng một tốc độ học cố định cho tất cả các trọng số, AdaGrad tính toán tốc độ học riêng biệt cho từng trọng số dựa trên lịch sử gradient trước đó.

Công thức cập nhật trọng số với AdaGrad:

• G t là tổng bình phương gradient tính đến thời điểm t.

• ϵ là một hằng số nhỏ để tránh chia cho 0. Ưu điểm:

• AdaGrad điều chỉnh tốc độ học tự động, giúp các trọng số có gradient lớn học chậm hơn và các trọng số có gradient nhỏ học nhanh hơn.

• Tốc độ học có thể giảm quá nhanh, dẫn đến việc mô hình không còn cập nhật hiệu quả sau một số vòng lặp nhất định.

RMSprop (Root Mean Square Propagation)

RMSprop là một phiên bản nâng cấp của thuật toán AdaGrad, với cách tiếp cận khác biệt trong việc xử lý gradient Thay vì tổng hợp tất cả các gradient trước đó, RMSprop tính toán trung bình của bình phương gradient trong một khoảng thời gian cố định Công thức cập nhật trọng số trong RMSprop được thể hiện như sau: v_t = βv_{t-1} + (1-β)∇w L(w)^2, và trọng số được cập nhật theo công thức w = w - η.

• v t là trung bình động của bình phương gradient.

• β là hệ số làm mượt (thường được chọn là 0.9).

• ϵ là hằng số nhỏ để tránh chia cho 0. Ưu điểm:

• Giúp cải thiện hiệu suất tối ưu hóa trong các bài toán có độ dốc không đều.

• Cập nhật hiệu quả hơn so với AdaGrad.

Adam (Adaptive Moment Estimation)

Thuật toán Adam là một trong những phương pháp tối ưu hóa mạnh mẽ và phổ biến nhất hiện nay, kết hợp hai ý tưởng quan trọng: tính toán momentum tương tự như SGD với momentum và điều chỉnh tốc độ học cho từng trọng số, giống như các phương pháp AdaGrad và RMSprop.

Công thức cập nhật trọng số với Adam: m t =β 1 mt−1+ (1−β 1 )∇ w L(w) v t =β 2 vt−1+ (1−β 2 )∇ w L(w) 2 ˆ m t = m t

• m t và v t là các ước lượng động lượng và bình phương động lượng.

• β1 và β2 là các hệ số động lượng (thường được chọn là 0.9 và 0.999).

• ϵ là một hằng số nhỏ để tránh chia cho 0. Ưu điểm:

• Adam tự động điều chỉnh tốc độ học và sử dụng cả thông tin về gradient và bình phương gradient.

• Có thể làm việc hiệu quả với cả dữ liệu nhỏ và lớn.

Nadam (Nesterov-accelerated Adaptive Moment Estimation)

Nadam là một phương pháp tối ưu hóa kết hợp giữa Adam và Momentum, trong đó momentum được tính toán trước khi gradient được tính Phương pháp này giúp tăng tốc độ hội tụ và giảm thiểu sự dao động trong quá trình huấn luyện mô hình.

Xây dựng mô hình phân lớp sử dụng

Julia using Flux using Images using ImageCore using FileIO using Random using Statistics using Plots

The `TạoDataset` function is designed to create a dataset by reading image files from a specified directory, resizing them to the given width and height, and normalizing the pixel values It scans the directory for files with extensions such as jpg, png, and jpeg, and for each valid image file, it loads the image, resizes it, and normalizes the data by scaling the pixel values to a range between 0 and 1 This process ensures that the images are prepared for further analysis or machine learning tasks.

# Chuyển sang Float32 img = convert(Matrix{RGB{Float32}}, img) end if typeof(img) == Matrix{RGB{Float32}}

# Thêm ảnh vào data và labels

The code snippet processes image files by checking their dimensions and formats It pushes the RGB channel view of the image into a data array while categorizing labels based on the presence of "HL" in the filename If the image is not in RGB format, it is skipped, and an error message is printed for any files that cannot be processed Additionally, non-image files are also disregarded.

# Ghép các ảnh và đảm bảo dữ liệu có kích thước đúng

Ensure that the data has the correct dimensions (height, width, channels, batch size) by concatenating it along the fourth dimension After concatenation, print the size of the data to verify the changes Next, reshape the labels into a column vector of type Float32 and display their size before and after the reshape operation Finally, return both the processed data and labels, with a specified resize value of 90.

# Tạo data và labels data_full, labels_full = TạoDataset("Data/Peach", resized, resized) println("Size data: ", size(data_full)) println("Size labels: ", size(labels_full))

# Chia dữ liệu thủ công

# Kích thước dữ liệu data_size = size(data_full) # (90, 90, 3, 2474) labels_size = size(labels_full) # (2474, 1)

# Tính số lượng mẫu num_samples = data_size[4] # Batch size (2474) train_ratio = 0.8 # Tỷ lệ train

# Số mẫu train (80% của 2474) num_train = Int(floor(train_ratio * num_samples))

# Shuffle dữ liệu indices = shuffle(1:num_samples)

# Chia chỉ số cho train và test train_indices = indices[1:num_train] # 80% đầu tiên test_indices = indices[num_train+1:end] # 20% còn lại

# Kích thước (90, 90, 3, num_train) train_data = data_full[:, :, :, train_indices]

# Kích thước (90, 90, 3, num_samples - num_train) test_data = data_full[:, :, :, test_indices]

# Kích thước (num_train, 1) train_labels = labels_full[train_indices, :]

# Kích thước (num_samples - num_train, 1) test_labels = labels_full[test_indices, :]

# (90, 90, 3, num_train) println("Kích thước train_data: ", size(train_data))

# (90, 90, 3, num_samples - num_train) println("Kích thước test_data: ", size(test_data))

# (num_train, 1) println("Kích thước train_labels: ", size(train_labels))

# (num_samples - num_train, 1) println("Kích thước test_labels: ", size(test_labels))

# Mô hình CNN model = Chain(

Flux.flatten, x -> begin println("Size after flatten: ", size(x)) # In kích thước sau flatten return x end,

Dense(14112, 128, relu), # Sử dụng đúng số lượng đầu vào cho lớp Dense

Dense(128, 1), x -> reshape(x, :, 1), # Reshape để có kích thước (batch_size, 1)

# Loss function loss_fn = (x, y) -> begin y = model(x)

To prevent log(0) errors, the value of y is clamped between 1e-7 and 1.0 - 1e-7 The code then prints the value of y for verification, along with the size of both predictions and labels Finally, it returns the binary cross-entropy calculated from y.

To manually create a DataLoader in Julia, define the function `create_dataloader(data, labels, batch_size, shuffle)` This function calculates the number of samples in the data using `n = size(data, 4)` If shuffling is enabled, it generates random indices with `indices = shuffle ? randperm(n) : 1:n` The batches are then created by slicing the indices into groups of the specified batch size, using the expression `batches = [indices[i:min(i + batch_size - 1, n)] for i in 1:batch_size:n]`.

Ensure that the labels have a size of (batch_size, 1) by returning the formatted data as [(data[:, :, :, b], reshape(labels[b], :, 1)) for b in batches] Set the batch_size to 80 and create the data loader using train_loader = create_dataloader(train_data, train_labels, batch_size, shuffle=true).

# Huấn luyện opt = Flux.Adam(0.001) epochs = 10 losses = [] # Mảng để lưu loss sau mỗi epoch for epoch in 1:epochs for (x, y) in train_loader

Flux.train!(loss_fn, Flux.params(model), [(x, y)], opt) end

During each training epoch, the model's loss is calculated using the training data and labels with the function `loss_fn(train_data, train_labels)` The loss for the current epoch is printed with the statement `println("Epoch $epoch, Loss: $train_loss")`, and the calculated loss is stored in the `losses` array using `push!(losses, train_loss)` This process continues for every epoch, allowing for the monitoring of the model's performance over time.

# Vẽ biểu đồ loss plot(1:epochs, losses, label="Loss", xlabel="Epoch", ylabel="Loss", title="Training Loss") savefig("loss_model2.png")

# Dự đoán trên tập test yHat_test = model(test_data) # Dự đoán của mô hình println("Predictions size: ", size(yHat_test))

# Nếu mô hình trả về 2 giá trị cho mỗi mẫu (cho phân loại nhị phân), sử dụng onecold if size(yHat_test, 2) == 2 yHat_test = Flux.onecold(yHat_test, 0:1) else

# Nếu mô hình trả về một giá trị xác suất, chuyển thành nhãn 0 hoặc 1 yHat_test = yHat_test > 0.5 end

# Đảm bảo labels có kích thước đúng

Ensure that the labels are formatted as a column vector (n, 1) by reshaping them with `test_labels = reshape(test_labels, :, 1)` Print the dimensions of the predictions after one-hot encoding using `println("Predictions after onecold: ", size(yHat_test))` and the ground truth labels after reshaping with `println("Ground truth labels after reshape: ", size(test_labels))` Calculate the accuracy by comparing the predicted labels to the ground truth with `accuracy = mean(yHat_test == test_labels)` and display the test accuracy using `println("Test Accuracy: ", accuracy)`.

# Tính các giá trị TP, TN, FP, FN

TP = sum((yHat_test == 1) & (test_labels == 1)) # True Positive

TN = sum((yHat_test == 0) & (test_labels == 0)) # True Negative

FP = sum((yHat_test == 1) & (test_labels == 0)) # False Positive

FN = sum((yHat_test == 0) & (test_labels == 1)) # False Negative

# Confusion matrix conf_matrix = [TP FP; FN TN]

# In kết quả println("Confusion Matrix:") println(conf_matrix)

# Vẽ confusion matrix labels = ["healthy", "bacterial spot"]

To create a heatmap using adjustable parameters, you can specify labels for both axes, a confusion matrix, and customize the x and y-axis labels with "Predicted" and "Actual." Set the title as "Confusion Matrix" and define the size of the heatmap to be 1000x1000 pixels Adjust the x-axis label rotation with the xrotation parameter and the y-axis label rotation with yrotation set to 0 Utilize a blue color scheme for the heatmap and modify the font size of the axis labels using guidefont set to font(12) and tickfont set to font(10) Finally, ensure the labels are centered within the cells by setting ticks to auto.

# Lưu hình ảnh heatmap vào tệp PNG savefig("confusion_matrix_model2.png")

Để tránh việc chia cho 0 khi tính Recall, cần kiểm tra trường hợp TP + FN = 0 Nếu TP + FN bằng 0, thì Recall sẽ được đặt là 0.0, hoặc có thể trả về một giá trị khác theo yêu cầu Ngược lại, Recall sẽ được tính bằng TP chia cho tổng TP và FN.

Để tránh việc chia cho 0 khi tính toán độ chính xác (Precision), cần kiểm tra trường hợp tổng số True Positive (TP) và False Positive (FP) bằng 0 Nếu TP + FP = 0, thì độ chính xác sẽ được đặt là 0.0, hoặc có thể trả về một giá trị khác theo yêu cầu Ngược lại, độ chính xác sẽ được tính bằng công thức TP / (TP + FP).

To prevent division by zero when calculating the F1 Score, check if the sum of precision and recall equals zero If precision plus recall equals zero, set the F1 Score to 0.0, or return a different value based on specific requirements Otherwise, calculate the F1 Score using the formula: F1 Score = 2 * (precision * recall) / (precision + recall).

Đoạn mã trên huấn luyện một mô hình học sâu với dữ liệu ảnh, sử dụng thư viện Flux.jl để xây dựng mô hình và Images.jl để xử lý ảnh Nó cũng tích hợp các thư viện khác để tạo dataset, tính toán các chỉ số đánh giá như Recall, Precision và F1 Score, cũng như vẽ đồ thị.

Tạo Dataset (Hàm TạoDataset)

Hàm TạoDataset nhận vào thư mục chứa ảnh, kích thước ảnh muốn thay đổi (width, height) và trả về tập dữ liệu (data) và nhãn (labels).

Mỗi hình ảnh trong thư mục sẽ được xử lý bằng cách đọc, thay đổi kích thước theo yêu cầu và chuẩn hóa giá trị pixel về khoảng [0, 1] Nếu hình ảnh không thuộc định dạng RGB, hàm sẽ tự động bỏ qua.

Mỗi ảnh được gán nhãn dựa trên tên file của nó Nếu tên file chứa chuỗi "HL", nhãn sẽ là 0, cho thấy đây có thể là ảnh của cây khỏe mạnh Ngược lại, nếu không có chuỗi "HL", nhãn sẽ là 1, cho thấy ảnh có thể liên quan đến bệnh bacterial spot.

• Sau khi xử lý ảnh, dữ liệu sẽ có định dạng (height,width,channels,batch_size).

Chuẩn Bị Dữ Liệu (Train và Test)

Sau khi tạo xong dataset, mã chia dữ liệu thành hai phần: 80% cho tập huấn luyện

(train) và 20% cho tập kiểm tra (test).

• Sử dụng shuffleđể xáo trộn dữ liệu trước khi chia thành tập train và test.

• Dữ liệu được chuẩn bị dưới dạng tensor 4 chiều cho mỗi batch: (height,width,3,num_samples).

Xây Dựng Mô Hình CNN

Mô hình sử dụng kiến trúc CNN (Convolutional Neural Network) với các lớp:

• Conv(3, 3): Lớp Convolution với kernel 3x3, từ 3 kênh (RGB) vào 16 kênh đầu ra.

• BatchNorm: Lớp chuẩn hóa để làm cho quá trình huấn luyện ổn định hơn.

• MaxPool(2, 2): Lớp Pooling để giảm kích thước của ảnh sau mỗi convolution.

• Flatten: Biến ảnh 2D thành vector 1D.

• Dense: Lớp fully connected với các node.

• (sigmoid): Lớp activation sigmoid để đưa đầu ra về giá trị xác suất cho phân loại nhị phân.

Hàm Mất Mát (Loss Function)

Hàm mất mát binary cross entropy là lựa chọn lý tưởng cho các bài toán phân loại nhị phân Để tránh lỗi khi tính toán log(0), giá trị dự đoán (ˆy) cần được "clamp" trước khi tính toán mất mát.

• Đoạn mã in kích thước của dự đoán và nhãn để kiểm tra tính đúng đắn của dữ liệu.

Tạo DataLoader Thủ Công

Hàmcreate_dataloadertạo ra các batch dữ liệu cho quá trình huấn luyện Dữ liệu và nhãn được chia thành các batch có kích thước batch_size.

• shuffle=true giúp xáo trộn dữ liệu mỗi lần gọi hàm, giúp cải thiện quá trình huấn luyện.

Huấn Luyện Mô Hình

Mô hình được huấn luyện trong 10 epoch sử dụng tối ưu hóa Adam.

• Sau mỗi epoch, hàm mất mát (train_loss) được tính toán và in ra Loss này được lưu vào mảng losses để vẽ đồ thị.

Đánh Giá Mô Hình

Sau khi huấn luyện, mô hình được kiểm tra trên tập test.

• Dự đoán (yHat_test) được tính cho tập test và nếu mô hình trả về xác suất, chúng được chuyển thành nhãn 0 hoặc 1.

• Đo độ chính xác của mô hình bằng cách so sánh dự đoán với nhãn thực tế (test_labels).

Confusion Matrix

Tính toán số lượng mẫu True Positive (TP), True Negative (TN), False Positive (FP), False Negative (FN).

Ma trận nhầm lẫn (confusion matrix) là công cụ quan trọng trong việc đánh giá hiệu suất của mô hình dự đoán Nó cung cấp thông tin về số lượng dự đoán chính xác (True Positive - TP, True Negative - TN) và sai (False Positive - FP, False Negative - FN) Để trực quan hóa dữ liệu, chúng ta có thể sử dụng heatmap để vẽ ma trận này, giúp dễ dàng nhận diện các kết quả dự đoán của mô hình.

Tính Các Chỉ Số Đánh Giá

• Recall: Tỷ lệ mẫu thực sự dương (positive) được mô hình dự đoán đúng.

• Precision: Tỷ lệ mẫu được mô hình dự đoán là dương mà thực tế là dương.

• F1 Score: Trung bình điều hòa của Recall và Precision, cung cấp một cái nhìn tổng quan về hiệu suất của mô hình.

Vẽ Biểu Đồ và Lưu Kết Quả

Sau khi huấn luyện xong, một biểu đồ thể hiện quá trình thay đổi của loss qua các epoch được vẽ và lưu lại dưới dạng file PNG.

• Ma trận nhầm lẫn cũng được vẽ dưới dạng heatmap và lưu thành file PNG.

Kết quả và đánh giá

Cuối cùng là phần đánh giá mô hình qua các chỉ số phân loại bao gồm accuracy, precision, recall và F1-score:

⋆ Accuracy: có thể được định nghĩa là số lần dự đoán đúng trên tổng số lần dự đoán.

Accuracy= Number of correct predictions

⋆ Precision: được định nghĩa là tỉ lệ số điểm Positive mô hình dự đoán đúng trên tổng số điểm mô hình dự đoán là Positive.

Precision = (True Positive) / (False Positive + True Positive) (5.2)

Recall được định nghĩa là tỷ lệ số điểm Positive mà mô hình dự đoán đúng so với tổng số điểm thực sự là Positive, tức là tổng số điểm được gán nhãn là Positive ban đầu.

Recall = True Positive / False Negative + True Positive (5.3)

⋆ F1-score : là trung bình điều hòa (harmonic mean) của precision và recall.

F1-score = 2 × ((Precision × Recall) / (Precision + Recall)) (5.4)

Ta có các kết quả nhận được từ việc thực thi mô hình và tổng hợp thành bảng:

Metric Value True Positive (TP) 1 False Positive (FP) 1 True Negative (TN) 81 False Negative (FN) 1 Test Accuracy 0.9926 Recall 0.9947 Precision 0.9947 F1 Score 0.9947

Mô hình phân loại đã thể hiện hiệu suất tốt khi áp dụng trên tập kiểm thử Hình ảnh dưới đây minh họa quá trình theo dõi lỗi huấn luyện qua 10 epochs cùng với ma trận lỗi tương ứng.

Hình 5.2: Lỗi huấn luyện qua 10 epochs.

Ta thấy lỗi huấn luyện giảm liên tục từ epoch thứ 6 đến 8 và ổn định cho đến epoch thứ10.

Trong quá trình xây dựng mô hình phân loại, tôi nhận thấy CNN hoạt động hiệu quả với dữ liệu hình ảnh, đúng với mục đích ban đầu của nó Tiểu luận này là cơ hội để tôi ôn tập và tìm hiểu sâu hơn về cách hoạt động của các mô hình mạng nơ ron liên quan đến dữ liệu tuần tự Tôi hy vọng những kiến thức được trình bày sẽ giúp bạn đọc có cái nhìn tổng quát về cách thức hoạt động của CNN.

Ngày đăng: 23/12/2024, 21:39

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w