Ghi nhật ký là một cách để lưu trữ thông tin về tập lệnh của bạn và theo dõi các sự kiện xảy ra. Khi viết bất kỳ tập lệnh phức tạp nào bằng Python, việc ghi nhật ký là điều cần thiết để gỡ lỗi phần mềm khi bạn phát triển phần mềm đó. Nếu không đăng nhập, việc tìm nguồn gốc của sự cố trong mã của bạn có thể cực kỳ tốn thời gian Show
Sau khi hoàn thành hướng dẫn này, bạn sẽ biết
Bắt đầu dự án của bạn với cuốn sách mới Python for Machine Learning của tôi, bao gồm các hướng dẫn từng bước và các tệp mã nguồn Python cho tất cả các ví dụ Bắt đầu nàoĐăng nhập bằng Python Hướng dẫn tổng quanHướng dẫn này được chia thành bốn phần;
Lợi ích của việc ghi nhật kýBạn có thể yêu cầu. “Tại sao không chỉ sử dụng in ấn?” Khi bạn chạy một thuật toán và muốn xác nhận rằng nó đang làm những gì bạn mong đợi, điều tự nhiên là thêm một số câu lệnh Với tính năng ghi nhật ký, bạn có thể xác định nơi xuất phát lệnh gọi ghi nhật ký, phân biệt mức độ nghiêm trọng giữa các thông báo và ghi thông tin vào một tệp, điều mà việc in ấn không thể thực hiện được. Ví dụ: chúng ta có thể bật và tắt thông báo từ một mô-đun cụ thể của chương trình lớn hơn. Chúng tôi cũng có thể tăng hoặc giảm mức độ chi tiết của thông báo ghi nhật ký mà không cần thay đổi nhiều mã Ghi nhật ký cơ bảnPython có một thư viện tích hợp sẵn, Hệ thống ghi nhật ký trong Python hoạt động theo một không gian tên phân cấp và các mức độ nghiêm trọng khác nhau. Tập lệnh Python có thể tạo trình ghi nhật ký trong một không gian tên và mỗi khi một thông báo được ghi, tập lệnh phải chỉ định mức độ nghiêm trọng của nó. Thông báo đã ghi có thể đi đến những nơi khác nhau tùy thuộc vào trình xử lý mà chúng tôi thiết lập cho không gian tên. Trình xử lý phổ biến nhất chỉ đơn giản là in trên màn hình, giống như hàm Có 5 cấp độ ghi nhật ký khác nhau cho biết mức độ nghiêm trọng của nhật ký, thể hiện ở mức độ nghiêm trọng tăng dần
Một ví dụ rất đơn giản về ghi nhật ký được hiển thị bên dưới, sử dụng trình ghi nhật ký mặc định hoặc trình ghi nhật ký gốc 1 2 3 4 5 6 7 nhập ghi nhật ký
ghi nhật ký. gỡ lỗi('Thông báo gỡ lỗi') ghi nhật ký. thông tin('Thông tin thông báo') ghi nhật ký. cảnh báo('Thông báo cảnh báo') ghi nhật ký. lỗi('Thông báo lỗi') ghi nhật ký. quan trọng('Thông báo quan trọng') Chúng sẽ phát ra các thông điệp tường trình có mức độ nghiêm trọng khác nhau. Trong khi có năm dòng ghi nhật ký, bạn chỉ có thể thấy ba dòng đầu ra nếu bạn chạy tập lệnh này, như sau 1 2 3 CẢNH BÁO. gốc. Đây là a thông báo cảnh báo LỖI. gốc. Đây là một thông báo lỗi message CỰC QUAN TRỌNG. gốc. Đây là a thông báo quan trọng This is because the root logger, by default, only prints the log messages of a severity level of WARNING or above. However, using the root logger this way is not much different from using the print() function The settings for the root logger are not set in stone. We can configure the root logger to output to a particular file, change its default severity level, and format the output. Here’s an example 1 2 3 4 5 6 7 8 9 10 11 nhập ghi nhật ký
logging. basicConfig(filename = 'file. log', level = logging. DEBUG, format = '%(asctime)s. %(levelname)s. %(name)s. %(message)s')
ghi nhật ký. gỡ lỗi('Thông báo gỡ lỗi') ghi nhật ký. thông tin('Thông tin thông báo') ghi nhật ký. cảnh báo('Thông báo cảnh báo') ghi nhật ký. lỗi('Thông báo lỗi') ghi nhật ký. quan trọng('Thông báo quan trọng') Running this script will produce no output to the screen but will have the following in the newly created file 1 2 3 4 5 2022-03-22 20. 41. 08,151. DEBUG. root. Debug message 2022-03-22 20. 41. 08,152. THÔNG TIN. root. Info message 2022-03-22 20. 41. 08,152. WARNING. root. Warning message 2022-03-22 20. 41. 08,152. ERROR. root. Error message 2022-03-22 20. 41. 08,152. BẠO KÍCH. root. Critical message The call to Note that now all five messages were output, so the default level that the root logger logs is now “DEBUG. ” The log record attributes (such as Although there is a default logger, we usually want to make and use other loggers that can be configured separately. This is because we may want a different severity level or format for different loggers. A new logger can be created with 1 logger = logging. getLogger("logger_name") Internally, the loggers are organized in a hierarchy. A logger created with 1 logger = logging. getLogger("parent. child") will be a child logger created under the logger with the name “ Upon creation, a child logger has all the properties of its parent logger until reconfigured. We can demonstrate this with the following example 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 nhập ghi nhật ký
# Create `parent. child` logger logger = logging. getLogger("parent. child")
# Emit a log message of level INFO, by default this is not print to the screen logger. info("this is info level")
# Create `parent` logger parentlogger = logging. getLogger("parent")
# Set parent's level to INFO and assign a new handler handler = logging. StreamHandler() handler. setFormatter(ghi nhật ký. Trình định dạng("%(asctime)s. %(name)s. %(tên cấp độ)s. %(message)s")) parentlogger. setLevel(ghi nhật ký. THÔNG TIN) parentlogger. addHandler(trình xử lý)
# Cho phép thiết bị ghi nhật ký con gửi lại thông điệp tường trình nhật ký. thông tin("đây lại là cấp độ thông tin") Đoạn mã này sẽ chỉ xuất ra một dòng 1 2022-03-28 19:23. 29,315. cha mẹ. con. THÔNG TIN. đây là thông tin cấp lại được tạo bởi đối tượng StreamHandler với chuỗi định dạng tùy chỉnh. Điều này chỉ xảy ra sau khi chúng tôi định cấu hình lại trình ghi nhật ký cho Cấu hình nâng cao để ghi nhật kýNhư chúng ta đã thấy trong ví dụ trước, chúng ta có thể định cấu hình bộ ghi mà chúng ta đã tạo Ngưỡng cấp độGiống như cấu hình cơ bản của bộ ghi gốc, chúng tôi cũng có thể định cấu hình đích đầu ra, mức độ nghiêm trọng và định dạng của bộ ghi. Sau đây là cách chúng tôi có thể đặt ngưỡng cấp độ của bộ ghi thành INFO 1 2 parent_logger = ghi nhật ký. getLogger("parent") parent_logger. setLevel(ghi nhật ký. THÔNG TIN) Giờ đây, các lệnh có mức độ nghiêm trọng INFO trở lên sẽ được ghi lại bởi parent_logger. Nhưng nếu đây là tất cả những gì bạn đã làm, bạn sẽ không thấy bất cứ điều gì từ Trình xử lý nhật kýChúng tôi có thể định cấu hình đích đầu ra của trình ghi nhật ký của mình bằng các trình xử lý. Trình xử lý chịu trách nhiệm gửi thông điệp tường trình đến đúng đích. Có một số loại trình xử lý; . Với Đây là một ví dụ về việc sử dụng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 nhập ghi nhật ký
# Thiết lập bộ ghi gốc và thêm trình xử lý tệp vào bộ ghi gốc logging. basicConfig(filename = 'file. log', cấp độ = ghi nhật ký. CẢNH BÁO, format = '%(asctime)s. %(levelname)s. %(name)s. %(message)s')
# Tạo trình ghi nhật ký, đặt cấp độ và thêm trình xử lý luồng parent_logger = ghi nhật ký. getLogger("parent") parent_logger. setLevel(ghi nhật ký. THÔNG TIN) parent_shandler = ghi nhật ký. StreamHandler() parent_logger. addHandler(parent_shandler)
# Thông báo nhật ký nghiêm trọng INFO hoặc cao hơn sẽ được xử lý parent_logger. gỡ lỗi('Thông báo gỡ lỗi') parent_logger. thông tin('Thông tin thông báo') parent_logger. cảnh báo('Thông báo cảnh báo') parent_logger. lỗi('Thông báo lỗi') parent_logger. quan trọng('Thông báo quan trọng') Trong đoạn mã trên, có hai trình xử lý được tạo. Một Lưu ý rằng mặc dù có một 1 2 3 4 tin nhắn thông tin Tin nhắn cảnh báo Thông báo lỗi thông điệp quan trọng Nhưng đầu ra của thiết bị đầu cuối không được định dạng, vì chúng tôi chưa sử dụng 1 2 3 4 2022-03-22 23. 07. 12,533. THÔNG TIN. cha mẹ. tin nhắn thông tin 2022-03-22 23. 07. 12,533. CẢNH BÁO. cha mẹ. Tin nhắn cảnh báo 2022-03-22 23. 07. 12,533. LỖI. cha mẹ. Thông báo lỗi 2022-03-22 23. 07. 12,533. BẠO KÍCH. cha mẹ. thông điệp quan trọng Ngoài ra, chúng ta có thể sử dụng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 nhập ghi nhật ký
# Thiết lập bộ ghi gốc và thêm trình xử lý tệp vào bộ ghi gốc logging. basicConfig(filename = 'file. log', cấp độ = ghi nhật ký. CẢNH BÁO, format = '%(asctime)s. %(levelname)s. %(name)s. %(message)s')
# Tạo trình ghi nhật ký, đặt cấp độ và thêm trình xử lý luồng parent_logger = ghi nhật ký. getLogger("parent") parent_logger. setLevel(ghi nhật ký. THÔNG TIN) parent_fhandler = ghi nhật ký. Trình xử lý tệp('parent. log') parent_fhandler. setLevel(ghi nhật ký. CẢNH BÁO) parent_logger. addHandler(parent_fhandler)
# Thông báo nhật ký nghiêm trọng INFO hoặc cao hơn sẽ được xử lý parent_logger. gỡ lỗi('Thông báo gỡ lỗi') parent_logger. thông tin('Thông tin thông báo') parent_logger. cảnh báo('Thông báo cảnh báo') parent_logger. lỗi('Thông báo lỗi') parent_logger. quan trọng('Thông báo quan trọng') Ví dụ trên đã chứng minh rằng bạn cũng có thể đặt cấp độ của trình xử lý. Cấp độ Trong trường hợp này, đầu ra của 1 2 3 Tin nhắn cảnh báo Thông báo lỗi thông điệp quan trọng trong khi đó của
Trình định dạngĐể cấu hình định dạng của logger, chúng tôi sử dụng một 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 nhập ghi nhật ký
# Thiết lập bộ ghi gốc và thêm trình xử lý tệp vào bộ ghi gốc logging. basicConfig(filename = 'file. log', cấp độ = ghi nhật ký. CẢNH BÁO, format = '%(asctime)s. %(levelname)s. %(name)s. %(message)s')
# Tạo trình ghi nhật ký, đặt cấp độ và thêm trình xử lý luồng parent_logger = ghi nhật ký. getLogger("parent") parent_logger. setLevel(ghi nhật ký. THÔNG TIN) parent_fhandler = ghi nhật ký. Trình xử lý tệp('parent. log') parent_fhandler. setLevel(ghi nhật ký. CẢNH BÁO) parent_formatter = ghi nhật ký. Trình định dạng('%(asctime)s. %(tên cấp độ)s. %(message)s') parent_fhandler. setFormatter(parent_formatter) parent_logger. addHandler(parent_fhandler)
# Thông báo nhật ký nghiêm trọng INFO hoặc cao hơn sẽ được xử lý parent_logger. gỡ lỗi('Thông báo gỡ lỗi') parent_logger. thông tin('Thông tin thông báo') parent_logger. cảnh báo('Thông báo cảnh báo') parent_logger. lỗi('Thông báo lỗi') parent_logger. quan trọng('Thông báo quan trọng') Đầu tiên, chúng tôi tạo một trình định dạng, sau đó đặt trình xử lý của chúng tôi để sử dụng trình định dạng đó. Nếu muốn, chúng tôi có thể tạo một số trình ghi nhật ký, trình xử lý và trình định dạng khác nhau để chúng tôi có thể kết hợp và kết hợp dựa trên sở thích của mình Trong ví dụ này, 1 2 3 2022-03-23 13. 28. 31,302. CẢNH BÁO. Tin nhắn cảnh báo 2022-03-23 13. 28. 31,302. LỖI. Thông báo lỗi 2022-03-23 13. 28. 31,303. BẠO KÍCH. thông điệp quan trọng và 1 2 3 4 2022-03-23 13. 28. 31,302. THÔNG TIN. cha mẹ. tin nhắn thông tin 2022-03-23 13. 28. 31,302. CẢNH BÁO. cha mẹ. Tin nhắn cảnh báo 2022-03-23 13. 28. 31,302. LỖI. cha mẹ. Thông báo lỗi 2022-03-23 13. 28. 31,303. BẠO KÍCH. cha mẹ. thông điệp quan trọng Dưới đây là trực quan hóa luồng trình ghi nhật ký, trình xử lý và trình định dạng từ Biểu đồ luồng của trình ghi nhật ký và trình xử lý trong mô-đun ghi nhật ký Một ví dụ về việc sử dụng ghi nhật kýHãy coi thuật toán Nadam là một ví dụ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 # tối ưu hóa độ dốc gốc với nadam cho chức năng kiểm tra hai chiều từ toán học nhập sqrt từ numpy nhập asarray từ numpy. ngẫu nhiên nhập ranh giới từ numpy. ngẫu nhiên nhập hạt
# hàm mục tiêu def mục tiêu(x, y): return x**2. 0 + y**2. 0
# đạo hàm của hàm mục tiêu def đạo hàm(x, y): trả về xáo trộn([x * 2.0, y * 2. 0])
# thuật toán giảm độ dốc với nadam def nadam(mục tiêu, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8): # tạo điểm ban đầu x = giới hạn[. , 0] + rand . (len(bounds)) * (bounds[:, 1] - giới hạn . [:, 0]) điểm = mục tiêu(x[0], x[1]) # khởi tạo đường trung bình động giảm dần m = [0. 0 cho _ trong phạm vi . bounds.hình dạng[0])] n = [0. 0 cho _ trong phạm vi . bounds.hình dạng[0])] # chạy giảm độ dốc cho t trong phạm vi(n_iter): # tính độ dốc g(t) g = đạo hàm(x[0], x[1]) # xây dựng giải pháp từng biến một cho i trong phạm vi(bounds.hình dạng[0]) . : # m(t) = mu * m(t-1) + (1 - mu) * g(t) m[i] = mu * m[i] + (1.0 - mu) * g[i] # n(t) = nu * n(t-1) + (1 - nu) * g(t)^2 n[i] = nu * n[i] + (1.0 - nu) * g[i]**2 # mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu)) mhat = (mu * m[i] / (1.0 - mu)) . 0 ((1 - mu) * g[i] / (1.0 - mu)) # nhat = nu * n(t) / (1 - nu) nhat = nu * n[i] / (1.0 - nu) # x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat # đánh giá điểm ứng viên điểm = mục tiêu(x[0], x[1]) # báo cáo tiến độ in('>%d f(%s) = %. 5f' % (t, x, score)) return [x, điểm]
# gieo trình tạo số giả ngẫu nhiên hạt(1) # xác định phạm vi cho đầu vào giới hạn = xáo trộn([[-1.0, 1. 0], [- . 0, 1. 0]]) # xác định tổng số lần lặp n_iter = 50 # kích thước bước alpha = 0. 02 # yếu tố cho độ dốc trung bình mu = 0. 8 # hệ số cho độ dốc bình phương trung bình nu = 0. 999 # thực hiện tìm kiếm giảm độ dốc với nadam tốt nhất, điểm = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu) in('Xong. ') in('f(%s) = %f' % (best, score)) Trường hợp sử dụng đơn giản nhất là sử dụng ghi nhật ký để thay thế hàm 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 .. .
nhập ghi nhật ký
.. .
# Thêm. Tạo logger và chỉ định trình xử lý ghi nhật ký = ghi nhật ký. getLogger("nadam") trình xử lý = ghi nhật ký. StreamHandler() trình xử lý. setFormatter(ghi nhật ký. Trình định dạng("%(asctime)s. %(tên cấp độ)s. %(name)s. %(message)s")) nhật ký. addHandler(trình xử lý) nhật ký. setLevel(ghi nhật ký. GỠ LỖI) # gieo trình tạo số giả ngẫu nhiên hạt(1) .. . # đoạn mã còn lại Chúng tôi phải chỉ định một trình xử lý vì chúng tôi chưa bao giờ định cấu hình bộ ghi gốc và đây sẽ là trình xử lý duy nhất từng được tạo. Sau đó, trong chức năng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 .. .
# thuật toán giảm độ dốc với nadam def nadam(mục tiêu, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8): # Tạo trình ghi nhật ký ghi nhật ký = ghi nhật ký. getLogger("nadam") # tạo điểm ban đầu x = giới hạn[:, 0] + rand . (len(bounds)) * (bounds[:, 1] - giới hạn . [:, 0]) score = objective(x[0], x[1]) # initialize decaying moving averages m = [0. 0 for _ in range(bounds. shape[0])] n = [0. 0 for _ in range(bounds. shape[0])] # run the gradient descent for t in range(n_iter). # calculate gradient g(t) g = đạo hàm(x[0], x[1]) # build a solution one variable at a time for i in range(bounds. shape[0]). # m(t) = mu * m(t-1) + (1 - mu) * g(t) m[i] = mu * m[i] + (1. 0 - mu) * g[i] # n(t) = nu * n(t-1) + (1 - nu) * g(t)^2 n[i] = nu * n[i] + (1. 0 - nu) * g[i]**2 # mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu)) mhat = (mu * m[i] / (1. 0 - mu)) + ((1 - mu) * g[i] / (1. 0 - mu)) # nhat = nu * n(t) / (1 - nu) nhat = nu * n[i] / (1. 0 - nu) # x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat # evaluate candidate point score = objective(x[0], x[1]) # report progress using logger logger. info('>%d f(%s) = %. 5f' % (t, x, score)) return [x, score]
.. . If we are interested in the deeper mechanics of the Nadam algorithm, we may add more logs. The following is the complete code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 # tối ưu hóa độ dốc gốc với nadam cho chức năng kiểm tra hai chiều nhập ghi nhật ký từ toán học nhập sqrt từ numpy nhập asarray từ numpy. ngẫu nhiên nhập ranh giới từ numpy. ngẫu nhiên nhập hạt
# hàm mục tiêu def mục tiêu(x, y): return x**2. 0 + y**2. 0
# đạo hàm của hàm mục tiêu def đạo hàm(x, y): return asarray([x * 2. 0, y * 2. 0])
# thuật toán giảm độ dốc với nadam def nadam(mục tiêu, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8): ghi nhật ký = ghi nhật ký. getLogger("nadam") # tạo điểm ban đầu x = giới hạn[:, 0] + rand . (len(bounds)) * (bounds[:, 1] - giới hạn . [:, 0]) score = objective(x[0], x[1]) # initialize decaying moving averages m = [0. 0 for _ in range(bounds. shape[0])] n = [0. 0 for _ in range(bounds. shape[0])] # run the gradient descent for t in range(n_iter). iterlogger = logging. getLogger("nadam. iter") # calculate gradient g(t) g = đạo hàm(x[0], x[1]) # build a solution one variable at a time for i in range(bounds. shape[0]). # m(t) = mu * m(t-1) + (1 - mu) * g(t) m[i] = mu * m[i] + (1. 0 - mu) * g[i] # n(t) = nu * n(t-1) + (1 - nu) * g(t)^2 n[i] = nu * n[i] + (1. 0 - nu) * g[i]**2 # mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu)) mhat = (mu * m[i] / (1. 0 - mu)) + ((1 - mu) * g[i] / (1. 0 - mu)) # nhat = nu * n(t) / (1 - nu) nhat = nu * n[i] / (1. 0 - nu) # x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat iterlogger. info("Iteration %d variable %d. mhat=%f nhat=%f", t, i, mhat, nhat) # evaluate candidate point score = objective(x[0], x[1]) # report progress logger. info('>%d f(%s) = %. 5f' % (t, x, score)) return [x, score]
# Create logger and assign handler ghi nhật ký = ghi nhật ký. getLogger("nadam") trình xử lý = ghi nhật ký. StreamHandler() trình xử lý. setFormatter(ghi nhật ký. Trình định dạng("%(asctime)s. %(tên cấp độ)s. %(name)s. %(message)s")) nhật ký. addHandler(trình xử lý) nhật ký. setLevel(ghi nhật ký. GỠ LỖI) logger = logging. getLogger("nadam. iter") logger. setLevel(logging. INFO) # gieo trình tạo số giả ngẫu nhiên hạt(1) # xác định phạm vi cho đầu vào giới hạn = xáo trộn([[-1.0, 1. 0], [- . 0, 1. 0]]) # xác định tổng số lần lặp n_iter = 50 # kích thước bước alpha = 0. 02 # yếu tố cho độ dốc trung bình mu = 0. 8 # hệ số cho độ dốc bình phương trung bình nu = 0. 999 # thực hiện tìm kiếm giảm độ dốc với nadam tốt nhất, điểm = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu) in('Xong. ') in('f(%s) = %f' % (best, score)) We prepared two level of loggers, 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 2022-03-29 12. 24. 59,421. INFO. nadam. iter. Iteration 0 variable 0. mhat=-0. 597442 nhat=0. 110055 2022-03-29 12. 24. 59,421. INFO. nadam. iter. Iteration 0 variable 1. mhat=1. 586336 nhat=0. 775909 2022-03-29 12. 24. 59,421. INFO. nadam. >0 f([-0. 12993798 0. 40463097]) = 0. 18061 2022-03-29 12. 24. 59,421. INFO. nadam. iter. Iteration 1 variable 0. mhat=-0. 680200 nhat=0. 177413 2022-03-29 12. 24. 59,421. INFO. nadam. iter. Iteration 1 variable 1. mhat=2. 020702 nhat=1. 429384 2022-03-29 12. 24. 59,421. THÔNG TIN. nadam. >1 f([-0. 09764012 0. 37082777]) = 0. 14705 2022-03-29 12. 24. 59,421. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 2 biến 0. mhat=-0. 687764 nhat=0. 215332 2022-03-29 12. 24. 59,421. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 2 biến 1. mhat=2. 304132 nhat=1. 977457 2022-03-29 12. 24. 59,421. THÔNG TIN. nadam. >2 f([-0. 06799761 0. 33805721]) = 0. 11891 ... 2022-03-29 12. 24. 59,449. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 49 biến 0. mhat=-0. 000482 nhat=0. 246709 2022-03-29 12. 24. 59,449. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 49 biến 1. mhat=-0. 018244 nhat=3. 966938 2022-03-29 12. 24. 59,449. THÔNG TIN. nadam. >49 f([-5. 54299505e-05 -1. 00116899e-03]) = 0. 00000 Xong f([-5. 54299505e-05 -1. 00116899e-03]) = 0. 000001 Đặt các trình ghi nhật ký khác nhau không chỉ cho phép chúng tôi đặt cấp độ hoặc trình xử lý khác nhau mà còn cho phép chúng tôi phân biệt thông báo nhật ký đến từ đâu bằng cách xem tên của trình ghi nhật ký từ thông báo được in Trên thực tế, một mẹo hữu ích là tạo trình trang trí ghi nhật ký và áp dụng trình trang trí cho một số chức năng. Chúng ta có thể theo dõi mỗi khi chức năng đó được gọi. Ví dụ: chúng tôi đã tạo một trình trang trí bên dưới và áp dụng nó cho các chức năng 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 .. .
# Trình trang trí Python để ghi nhật ký lệnh gọi hàm và giá trị trả về def loggingdecorator(name): ghi nhật ký = ghi nhật ký. getLogger(tên) def _decor(fn): tên_hàm = fn. __name__ def _fn(*args, **kwargs): ret = fn(*args, **kwargs) argstr = [str(x) for x in args] argstr += [key+"="+str(val) for key,val in kwargs.mặt hàng()] máy ghi. gỡ lỗi("%s(%s) -> %s" . function_name, ", ".tham gia(argstr), ret) return ret return _fn return _decor
# hàm mục tiêu @loggingdecorator("nadam. chức năng") def mục tiêu(x, y): return x**2. 0 + y**2. 0
# đạo hàm của hàm mục tiêu @loggingdecorator("nadam. chức năng") def đạo hàm(x, y): return asarray([x * 2. 0, y * 2. 0]) Sau đó, chúng ta sẽ thấy những điều sau đây trong nhật ký 1 2 3 4 5 6 7 8 9 10 11 12 13 14 2022-03-29 13. 14. 07,542. GỠ LỖI. nadam. hàm số. mục tiêu(-0. 165955990594852, 0. 4406489868843162) -> 0. 22171292045649288 2022-03-29 13. 14. 07,542. GỠ LỖI. nadam. hàm số. đạo hàm(-0. 165955990594852, 0. 4406489868843162) -> [-0. 33191198 0. 88129797] 2022-03-29 13. 14. 07,542. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 0 biến 0. mhat=-0. 597442 nhat=0. 110055 2022-03-29 13. 14. 07,542. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 0 biến 1. mhat=1. 586336 nhat=0. 775909 2022-03-29 13. 14. 07,542. GỠ LỖI. nadam. hàm số. mục tiêu(-0. 12993797816930272, 0. 4046309737819536) -> 0. 18061010311445824 2022-03-29 13. 14. 07,543. THÔNG TIN. nadam. >0 f([-0. 12993798 0. 40463097]) = 0. 18061 2022-03-29 13. 14. 07,543. GỠ LỖI. nadam. hàm số. đạo hàm(-0. 12993797816930272, 0. 4046309737819536) -> [-0. 25987596 0. 80926195] 2022-03-29 13. 14. 07,543. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 1 biến 0. mhat=-0. 680200 nhat=0. 177413 2022-03-29 13. 14. 07,543. THÔNG TIN. nadam. lặp đi lặp lại. Lặp 1 biến 1. mhat=2. 020702 nhat=1. 429384 2022-03-29 13. 14. 07,543. GỠ LỖI. nadam. hàm số. mục tiêu(-0. 09764011794760165, 0. 3708277653552375) -> 0. 14704682419118062 2022-03-29 13. 14. 07,543. THÔNG TIN. nadam. >1 f([-0. 09764012 0. 37082777]) = 0. 14705 2022-03-29 13. 14. 07,543. GỠ LỖI. nadam. hàm số. đạo hàm(-0. 09764011794760165, 0. 3708277653552375) -> [-0. 19528024 0. 74165553] 2022-03-29 13. 14. 07,543. THÔNG TIN. nadam. lặp đi lặp lại. Lặp lại 2 biến 0. mhat=-0. 687764 nhat=0. 215332 ... nơi chúng ta có thể thấy các tham số và giá trị trả về của mỗi cuộc gọi đến hai hàm đó trong thông báo được ghi bởi bộ ghi nhật ký Bạn muốn bắt đầu với Python cho Machine Learning?Tham gia khóa học xử lý sự cố email miễn phí trong 7 ngày của tôi ngay bây giờ (có mã mẫu) Nhấp để đăng ký và cũng nhận được phiên bản PDF Ebook miễn phí của khóa học Tải xuống khóa học nhỏ MIỄN PHÍ của bạn Khi chúng tôi nhận được ngày càng nhiều thông báo tường trình, màn hình thiết bị đầu cuối sẽ trở nên rất bận rộn. Một cách để giúp theo dõi các vấn đề dễ dàng hơn là đánh dấu nhật ký bằng màu với mô-đun 1 pip cài đặt colorama Dưới đây là ví dụ về cách bạn có thể sử dụng mô-đun 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 nhập ghi nhật ký nhập colorama từ colorama nhập Fore, Back, Style
# Khởi tạo thiết bị đầu cuối cho màu sắc colorama. init(tự động đặt lại = True)
# Thiết lập nhật ký như bình thường ghi nhật ký = ghi nhật ký. getLogger("color") nhật ký. setLevel(ghi nhật ký. GỠ LỖI) trình xử lý = ghi nhật ký. StreamHandler() trình định dạng = ghi nhật ký. Trình định dạng('%(asctime)s. %(tên cấp độ)s. %(name)s. %(message)s') người xử lý. setFormatter(bộ định dạng) nhật ký. addHandler(handler)
# Phát ra thông điệp tường trình với màu sắc nhật ký. gỡ lỗi('Thông báo gỡ lỗi') nhật ký. vào(Đối với. XANH LỤC + 'Thông báo thông tin') nhật ký. cảnh báo(Trước. BLUE + 'Thông báo cảnh báo') nhật ký. lỗi(Trước. VÀNG + Kiểu dáng. SÁNG + 'Thông báo lỗi') nhật ký. quan trọng(Trước. ĐỎ + Quay lại. VÀNG + Kiểu dáng. SÁNG + 'Thông báo quan trọng') Từ thiết bị đầu cuối, bạn sẽ thấy như sau trong đó Trên thực tế, chúng ta có thể dẫn xuất lớp 1 2 3 4 5 6 7 8 9 .. . colors = {"DEBUG". Dành cho. XANH DƯƠNG, "THÔNG TIN". Cho. CYAN, "CẢNH BÁO". Cho. VÀNG, "ERROR". Trước. ĐỎ, "CẤM". Trước. MAGENTA} lớp ColoredFormatter(ghi nhật ký. Trình định dạng). def định dạng(chính, record): tin nhắn = ghi nhật ký. Trình định dạng. định dạng(bản thân, bản ghi) nếu ghi. tên cấp độ trong màu sắc. tin nhắn = màu sắc[record.tên cấp độ] + tin nhắn + . Fore.ĐẶT LẠI trả về tin nhắn và sử dụng cái này thay cho 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 # tối ưu hóa độ dốc gốc với nadam cho chức năng kiểm tra hai chiều nhập ghi nhật ký nhập colorama từ colorama nhập Fore
từ toán học nhập sqrt từ numpy nhập asarray từ numpy. ngẫu nhiên nhập ranh giới từ numpy. ngẫu nhiên nhập hạt
def loggingdecorator(name): ghi nhật ký = ghi nhật ký. getLogger(tên) def _decor(fn): tên_hàm = fn. __name__ def _fn(*args, **kwargs): ret = fn(*args, **kwargs) argstr = [str(x) for x in args] argstr += [key+"="+str(val) for key,val in kwargs.mặt hàng()] máy ghi. gỡ lỗi("%s(%s) -> %s" . function_name, ", ".tham gia(argstr), ret) return ret return _fn return _decor
# hàm mục tiêu @loggingdecorator("nadam. chức năng") def mục tiêu(x, y): return x**2. 0 + y**2. 0
# đạo hàm của hàm mục tiêu @loggingdecorator("nadam. chức năng") def đạo hàm(x, y): return asarray([x * 2. 0, y * 2. 0])
# thuật toán giảm độ dốc với nadam def nadam(mục tiêu, derivative, bounds, n_iter, alpha, mu, nu, eps=1e-8): ghi nhật ký = ghi nhật ký. getLogger("nadam") # tạo điểm ban đầu x = giới hạn[:, 0] + rand . (len(bounds)) * (bounds[:, 1] - giới hạn . [:, 0]) score = objective(x[0], x[1]) # initialize decaying moving averages m = [0. 0 for _ in range(bounds. shape[0])] n = [0. 0 for _ in range(bounds. shape[0])] # run the gradient descent for t in range(n_iter). iterlogger = logging. getLogger("nadam. iter") # calculate gradient g(t) g = đạo hàm(x[0], x[1]) # build a solution one variable at a time for i in range(bounds. shape[0]). # m(t) = mu * m(t-1) + (1 - mu) * g(t) m[i] = mu * m[i] + (1. 0 - mu) * g[i] # n(t) = nu * n(t-1) + (1 - nu) * g(t)^2 n[i] = nu * n[i] + (1. 0 - nu) * g[i]**2 # mhat = (mu * m(t) / (1 - mu)) + ((1 - mu) * g(t) / (1 - mu)) mhat = (mu * m[i] / (1. 0 - mu)) + ((1 - mu) * g[i] / (1. 0 - mu)) # nhat = nu * n(t) / (1 - nu) nhat = nu * n[i] / (1. 0 - nu) # x(t) = x(t-1) - alpha / (sqrt(nhat) + eps) * mhat x[i] = x[i] - alpha / (sqrt(nhat) + eps) * mhat iterlogger. info("Iteration %d variable %d. mhat=%f nhat=%f", t, i, mhat, nhat) # evaluate candidate point score = objective(x[0], x[1]) # report progress máy ghi. cảnh báo('>%d f(%s) = %. 5f' % (t, x, score)) return [x, score]
# Chuẩn bị định dạng màu colorama. init(tự động đặt lại = True) colors = {"DEBUG". Dành cho. XANH DƯƠNG, "THÔNG TIN". Cho. CYAN, "CẢNH BÁO". Cho. VÀNG, "ERROR". Trước. ĐỎ, "CẤM". Trước. MAGENTA} lớp ColoredFormatter(ghi nhật ký. Trình định dạng). def định dạng(chính, record): tin nhắn = ghi nhật ký. Trình định dạng. định dạng(bản thân, bản ghi) nếu ghi. tên cấp độ trong màu sắc. tin nhắn = màu sắc[record.tên cấp độ] + tin nhắn + . Fore.ĐẶT LẠI trả về tin nhắn
# Create logger and assign handler ghi nhật ký = ghi nhật ký. getLogger("nadam") trình xử lý = ghi nhật ký. StreamHandler() trình xử lý. setFormatter(ColoredFormatter(" . %(tên cấp độ)s. %(name)s. %(tin nhắn)s")) nhật ký. addHandler(trình xử lý) nhật ký. setLevel(ghi nhật ký. GỠ LỖI) logger = logging. getLogger("nadam. iter") nhật ký. setLevel(ghi nhật ký. GỠ LỖI) # gieo trình tạo số giả ngẫu nhiên hạt(1) # xác định phạm vi cho đầu vào giới hạn = xáo trộn([[-1.0, 1. 0], [- . 0, 1. 0]]) # xác định tổng số lần lặp n_iter = 50 # kích thước bước alpha = 0. 02 # yếu tố cho độ dốc trung bình mu = 0. 8 # hệ số cho độ dốc bình phương trung bình nu = 0. 999 # thực hiện tìm kiếm giảm độ dốc với nadam tốt nhất, điểm = nadam(objective, derivative, bounds, n_iter, alpha, mu, nu) in('Xong. ') in('f(%s) = %f' % (best, score)) Nếu chúng ta chạy nó trên một thiết bị đầu cuối hỗ trợ, chúng ta sẽ thấy đầu ra sau Lưu ý rằng đầu ra đầy màu sắc có thể giúp chúng tôi phát hiện mọi hành vi bất thường dễ dàng hơn. Ghi nhật ký giúp gỡ lỗi và cũng cho phép chúng tôi dễ dàng kiểm soát mức độ chi tiết mà chúng tôi muốn xem bằng cách chỉ thay đổi một vài dòng mã Cách ghi nhật ký được sử dụng trong Python?Mô-đun ghi nhật ký
. Với mô-đun ghi nhật ký đã được nhập, bạn có thể sử dụng thứ gọi là “trình ghi nhật ký” để ghi nhật ký các tin nhắn mà bạn muốn xem. integrate your log messages with the ones from those libraries to produce a homogeneous log for your application. With the logging module imported, you can use something called a “logger” to log messages that you want to see.
Ghi nhật ký Python có được tích hợp sẵn không?Python có ghi nhật ký mô-đun tích hợp sẵn cho phép ghi thông báo trạng thái vào một tệp hoặc bất kỳ luồng đầu ra nào khác.
Ghi nhật ký Python có sử dụng log4j không?log4j là gói ghi nhật ký phổ biến được viết bằng Java. log4j đã được chuyển sang các ngôn ngữ C, C++, C#, Perl, Python, Ruby và Eiffel .
Ghi nhật ký Python có dễ bị tấn công không?Rất may, Việc ghi nhật ký của Python không dễ bị thực thi mã từ xa . Tuy nhiên, điều quan trọng vẫn là phải cẩn thận với dữ liệu không đáng tin cậy. Bài viết này sẽ mô tả một số cạm bẫy phổ biến và cách thực hành phổ biến của việc ghi chuỗi f có thể — trong một số trường hợp — khiến bạn dễ bị tấn công bởi các kiểu tấn công khác. |