Trình xử lý ghi nhật ký Python là gì?

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

Sau khi hoàn thành hướng dẫn này, bạn sẽ biết

  • Tại sao chúng tôi muốn sử dụng mô-đun ghi nhật ký
  • Cách sử dụng mô-đun ghi nhật ký
  • Cách tùy chỉnh cơ chế ghi nhật ký

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
Ảnh của ilaria88. Một số quyền được bảo lưu.

Hướng dẫn tổng quan

Hướng dẫn này được chia thành bốn phần;

  • Lợi ích của việc ghi nhật ký
  • ghi nhật ký cơ bản
  • Cấu hình nâng cao để đăng nhập
  • Một ví dụ về việc sử dụng ghi nhật ký

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, thì việc thêm một số câu lệnh print[] tại các vị trí chiến lược để hiển thị trạng thái của chương trình là điều đương nhiên. Tính năng in có thể giúp gỡ lỗi các tập lệnh đơn giản hơn, nhưng khi mã của bạn ngày càng phức tạp hơn, tính năng in sẽ thiếu tính linh hoạt và mạnh mẽ mà tính năng ghi nhật ký có được

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ản

Python có một thư viện tích hợp sẵn, logging, cho mục đích này. Thật đơn giản để tạo một “logger” để ghi lại các tin nhắn hoặc thông tin mà bạn muốn xem

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 là chỉ cần in trên màn hình, giống như hàm print[] phổ biến. Khi chúng tôi bắt đầu chương trình, chúng tôi có thể đăng ký một trình xử lý mới và thiết lập mức độ nghiêm trọng mà trình xử lý sẽ phản ứng

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

  1. GỠ LỖI
  2. THÔNG TIN
  3. CẢNH BÁO
  4. LỖI
  5. BẠO KÍCH

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 a thông báo cảnh báo

LỖI. gốc. Đây một thông báo lỗi message

CỰC QUAN TRỌNG. gốc. Đây a thông báo quan trọng

Điều này là do theo mặc định, trình ghi nhật ký gốc chỉ in các thông báo nhật ký ở mức độ nghiêm trọng CẢNH BÁO trở lên. Tuy nhiên, sử dụng root logger theo cách này không khác mấy so với sử dụng hàm print[]

Các cài đặt cho trình ghi gốc không được đặt cố định. Chúng tôi có thể định cấu hình bộ ghi gốc để xuất ra một tệp cụ thể, thay đổi mức độ nghiêm trọng mặc định của nó và định dạng đầu ra. Đây là một ví dụ

1

2

3

4

5

6

7

8

9

10

11

nhập ghi nhật ký

 

ghi nhật ký. basicConfig[tên tệp = ' . nhật ký',

                    cấp độ = ghi nhật ký. GỠ LỖI,

                    định dạng = '%[asctime]s. %[tên cấp độ]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']

Chạy tập lệnh này sẽ không tạo ra kết quả nào trên màn hình nhưng sẽ có phần sau trong tệp mới tạo file.log

1

2

3

4

5

2022-03-22 20. 41. 08,151. GỠ LỖI. nguồn gốc. Thông báo gỡ lỗi

2022-03-22 20. 41. 08,152. THÔNG TIN. nguồn gốc. tin nhắn thông tin

2022-03-22 20. 41. 08,152. CẢNH BÁO. nguồn gốc. Tin nhắn cảnh báo

2022-03-22 20. 41. 08,152. LỖI. nguồn gốc. Thông báo lỗi

2022-03-22 20. 41. 08,152. BẠO KÍCH. nguồn gốc. thông điệp quan trọng

Lệnh gọi tới logging.basicConfig[] là thay đổi trình ghi nhật ký gốc. Trong ví dụ của chúng tôi, chúng tôi đặt trình xử lý xuất thành tệp thay vì màn hình, điều chỉnh cấp độ ghi nhật ký sao cho tất cả thông báo tường trình ở cấp độ GỠ LỖI hoặc cao hơn đều được xử lý, đồng thời thay đổi định dạng của đầu ra thông báo tường trình để bao gồm thời gian

Lưu ý rằng bây giờ tất cả năm thông báo đã được xuất ra, do đó, mức mặc định mà bộ ghi nhật ký gốc hiện là “DEBUG. ” Có thể tìm thấy các thuộc tính bản ghi nhật ký [chẳng hạn như %[asctime]s] để định dạng đầu ra trong tài liệu ghi nhật ký

Mặc dù có một trình ghi nhật ký mặc định nhưng chúng tôi thường muốn tạo và sử dụng các trình ghi nhật ký khác có thể được cấu hình riêng. Điều này là do chúng tôi có thể muốn một mức độ nghiêm trọng hoặc định dạng khác nhau cho các trình ghi nhật ký khác nhau. Một logger mới có thể được tạo ra với

1

ghi nhật ký = ghi nhật ký. getLogger["logger_name"]

Trong nội bộ, các logger được tổ chức theo thứ bậc. Một logger được tạo bằng

1

ghi nhật ký = ghi nhật ký. getLogger["parent. child"]

sẽ là một trình ghi nhật ký con được tạo bên dưới trình ghi nhật ký có tên “parent”, đến lượt nó, nằm dưới trình ghi nhật ký gốc. Sử dụng dấu chấm trong chuỗi biểu thị rằng trình ghi con là con của trình ghi gốc. Trong trường hợp trên, một bộ ghi có tên “parent.child” được tạo cũng như một bộ ghi có tên "parent" ngầm định

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

ghi nhật ký = ghi nhật ký. getLogger["parent. child"]

 

# Emit a log message of level INFO, by default this is not print to the screen

logger. thông tin["đây là cấp độ thông tin"]

 

# Create `parent` logger

parentlogger = logging. getLogger["parent"]

 

# Đặt cấp độ của cha mẹ thành INFO và chỉ định trình xử lý mới

trình xử lý = ghi nhật ký. StreamHandler[]

handler. setFormatter[logging. Formatter["%[asctime]s. %[name]s. %[levelname]s. %[message]s"]]

parentlogger. setLevel[ghi nhật ký. INFO]

parentlogger. addHandler[handler]

 

# Let child logger emit a log message again

nhật ký. info["this is info level again"]

This code snippet will output only one line

1

2022-03-28 19. 23. 29,315. parent. child. INFO. this is info level again

which is created by the StreamHandler object with the customized format string. It happens only after we reconfigured the logger for parent because otherwise, the root logger’s configuration prevails, and no messages at level INFO will be printed

Advanced Configuration to Logging

As we saw in the last example, we can configure the loggers we made

Threshold of Level

Like the basic configuration of the root logger, we can also configure the output destination, severity level, and formatting of a logger. The following is how we can set the threshold of the level of a logger to INFO

1

2

parent_logger = logging. getLogger["parent"]

parent_logger. setLevel[logging. INFO]

Now commands with severity level INFO and higher will be logged by the parent_logger. But if this is all you did, you will not see anything from logging,0 because there are no handlers assigned for this logger. In fact, there are no handlers for root logger as well unless you set up one with logging.basicConfig[]

Log Handlers

We can configure the output destination of our logger with handlers. Handlers are responsible for sending the log messages to the correct destination. There are several types of handlers; the most common ones are logging,2 and logging,3. With logging,2, the logger will output to the terminal, while with logging,3, the logger will output to a particular file

Đây là một ví dụ về việc sử dụng logging,2 để xuất nhật ký ra thiết bị đầu cuối

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ý

 

# Set up root logger, and add a file handler to root logger

ghi nhật ký. basicConfig[tên tệp = ' . nhật ký',

                    level = logging. CẢNH BÁO,

                    định dạng = '%[asctime]s. %[tên cấp độ]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 = logging. getLogger["parent"]

parent_logger. setLevel[logging. INFO]

parent_shandler = logging. 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. debug['Debug message']

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 logging,3 được tạo bởi logging.basicConfig[] cho trình ghi nhật ký gốc và một logging,2 được tạo cho trình ghi nhật ký parent

Lưu ý rằng mặc dù có một logging,2 gửi nhật ký đến thiết bị đầu cuối, các nhật ký từ bộ ghi nhật ký parent vẫn được gửi đến file.log vì nó là con của bộ ghi nhật ký gốc và trình xử lý của bộ ghi nhật ký gốc cũng đang hoạt động đối với các thông điệp nhật ký của bộ ghi nhật ký con. We can see that the logs to the terminal include INFO level messages and above

1

2

3

4

Info message

Warning message

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 print[]4. Tuy nhiên, nhật ký của file.log đã thiết lập print[]4 và nó sẽ giống như sau

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 logging,3 trong ví dụ trên của print[]8

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ý

 

# Set up root logger, and add a file handler to root logger

ghi nhật ký. basicConfig[tên tệp = ' . nhật ký',

                    level = logging. CẢNH BÁO,

                    định dạng = '%[asctime]s. %[tên cấp độ]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 = logging. getLogger["parent"]

parent_logger. setLevel[logging. INFO]

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. debug['Debug message']

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 độ print[]9 lọc ra các nhật ký không ở cấp độ CẢNH BÁO hoặc cao hơn. Tuy nhiên, nếu bạn đặt cấp độ của trình xử lý thành GỠ LỖI, thì điều đó cũng giống như không đặt cấp độ vì nhật ký GỠ LỖI đã được lọc ra theo cấp độ của trình ghi nhật ký, đó là THÔNG TIN

Trong trường hợp này, đầu ra của file.log0 là

1

2

3

Warning message

Thông báo lỗi

thông điệp quan trọng

trong khi đó của file.log giống như trước đây. Tóm lại, khi một thông điệp nhật ký được ghi lại bởi một bộ ghi nhật ký,

  1. Cấp độ của trình ghi nhật ký sẽ xác định xem thông báo có đủ nghiêm trọng để xử lý hay không. Nếu cấp độ của trình ghi nhật ký không được đặt, thì cấp độ của trình ghi gốc [và cuối cùng là trình ghi nhật ký gốc] sẽ được sử dụng cho việc xem xét này
  2. Nếu thông báo nhật ký sẽ được xử lý, thì tất cả các trình xử lý đã từng được thêm dọc theo hệ thống phân cấp bộ ghi nhật ký cho đến bộ ghi nhật ký gốc sẽ nhận được một bản sao của thông báo. Mỗi cấp độ của trình xử lý sẽ xác định xem trình xử lý cụ thể này có tôn trọng thông báo này hay không

Trình định dạng

Để cấu hình định dạng của logger, chúng tôi sử dụng một print[]4. Nó cho phép chúng tôi đặt định dạng của nhật ký, tương tự như cách chúng tôi đã làm như vậy trong file.log3 của trình ghi nhật ký gốc. Đây là cách chúng tôi có thể thêm trình định dạng vào trình xử lý của mình

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ý

 

# Set up root logger, and add a file handler to root logger

ghi nhật ký. basicConfig[tên tệp = ' . nhật ký',

                    level = logging. CẢNH BÁO,

                    định dạng = '%[asctime]s. %[tên cấp độ]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 = logging. getLogger["parent"]

parent_logger. setLevel[logging. INFO]

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. debug['Debug message']

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, file.log0 sẽ có

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. Error message

2022-03-23 ​​13. 28. 31,303. BẠO KÍCH. thông điệp quan trọng

file.log được liên kết với trình xử lý tại bộ ghi gốc sẽ có

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ẹ. Critical message

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ừ tài liệu của mô-đun ghi nhật ký

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

# gradient descent optimization with nadam for a two-dimensional test function

from math import sqrt

từ numpy nhập asarray

from 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]:

# generate an initial point

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 for _ in range[bounds. shape[0]]]

n = [0. 0 cho _ trong phạm vi . bounds.shape[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.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]] . 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], [-1. 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

best, score = 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 print[]. Chúng ta có thể thực hiện thay đổi sau. Trước tiên, hãy tạo một trình ghi nhật ký có tên file.log7 trước khi chúng tôi chạy bất kỳ mã nào và gán một logging,2

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ý. Formatter["%[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ý. DEBUG]

# 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. Then, in the function file.log9, we re-create a logger logging.basicConfig[]0 but since it has already been set up, the level and handlers persisted. Ở cuối mỗi vòng lặp for bên ngoài trong file.log9, chúng tôi đã thay thế hàm print[] bằng logging.basicConfig[]3 để hệ thống ghi nhật ký xử lý thông báo

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 = bounds[. , 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.shape[0]]]

    # chạy giảm độ dốc

    cho t trong phạm vi[n_iter]:

        # calculate gradient g[t]

        g = đạo hàm[x[0], x[1]]

        # xây dựng giải pháp cho từng biến một

        cho i trong phạm vi[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]] . 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

        # evaluate candidate point

        điểm = mục tiêu[x[0], x[1]]

        # báo cáo tiến độ bằng trình ghi nhật ký

        máy ghi. thông tin['>%d f[%s] = %. 5f' % [t, x, score]]

    return [x, score]

 

. . .

Nếu chúng tôi quan tâm đến cơ chế sâu hơn của thuật toán Nadam, chúng tôi có thể thêm nhiều nhật ký hơn. Sau đây là mã hoàn chỉnh

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

# gradient descent optimization with nadam for a two-dimensional test function

nhập ghi nhật ký

from math import sqrt

từ numpy nhập asarray

from 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 = bounds[. , 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.shape[0]]]

    # chạy giảm độ dốc

    cho t trong phạm vi[n_iter]:

        iterlogger = ghi nhật ký. getLogger["nadam. iter"]

        # calculate gradient g[t]

        g = đạo hàm[x[0], x[1]]

        # xây dựng giải pháp cho từng biến một

        cho i trong phạm vi[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]] . 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

            iterlogger. thông tin["Lặp %d biến %d. mhat=%f nhat=%f", t, i, mhat, nhat]

        # evaluate candidate point

        điểm = mục tiêu[x[0], x[1]]

        # tiến trình báo cáo

        máy ghi. thông tin['>%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ý. Formatter["%[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ý. DEBUG]

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], [-1. 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

best, score = nadam[objective, derivative, bounds, n_iter, alpha, mu, nu]

in['Xong. ']

in['f[%s] = %f' % [best, score]]

We prepared two level of loggers, file.log7 and logging.basicConfig[]5, and set them in different levels. Trong vòng lặp bên trong của file.log9, chúng tôi sử dụng bộ ghi con để in một số biến nội bộ. When you run this script, it will print the following

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. INFO. nadam. >1 f[[-0. 09764012  0. 37082777]] = 0. 14705

2022-03-29 12. 24. 59,421. INFO. nadam. iter. Iteration 2 variable 0. mhat=-0. 687764 nhat=0. 215332

2022-03-29 12. 24. 59,421. INFO. nadam. iter. Iteration 2 variable 1. mhat=2. 304132 nhat=1. 977457

2022-03-29 12. 24. 59,421. INFO. nadam. >2 f[[-0. 06799761  0. 33805721]] = 0. 11891

...

2022-03-29 12. 24. 59,449. INFO. nadam. iter. Lặp lại 49 biến 0. mhat=-0. 000482 nhat=0. 246709

2022-03-29 12. 24. 59,449. INFO. nadam. iter. Iteration 49 variable 1. mhat=-0. 018244 nhat=3. 966938

2022-03-29 12. 24. 59,449. INFO. nadam. >49 f[[-5. 54299505e-05 -1. 00116899e-03]] = 0. 00000

Done

f[[-5. 54299505e-05 -1. 00116899e-03]] = 0. 000001

Setting different loggers not only allows us to set a different level or handlers, but it also lets us differentiate where the log message comes from by looking at the logger’s name from the message printed

In fact, one handy trick is to create a logging decorator and apply the decorator to some functions. We can keep track of every time that function is called. For example, we created a decorator below and applied it to the functions logging.basicConfig[]7 and logging.basicConfig[]8

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

. . .

 

# A Python decorator to log the function call and return value

def loggingdecorator[name].

    logger = logging. getLogger[name]

    def _decor[fn].

        function_name = 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. items[]]

            logger. debug["%s[%s] -> %s", function_name, ", ". join[argstr], ret]

            return ret

        return _fn

    return _decor

 

# hàm mục tiêu

@loggingdecorator["nadam. function"]

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. function"]

def đạo hàm[x, y]:

    return asarray[[x * 2. 0, y * 2. 0]]

Then we will see the following in the log

1

2

3

4

5

6

7

8

9

10

11

12

13

14

2022-03-29 13. 14. 07,542. DEBUG. nadam. function. objective[-0. 165955990594852, 0. 4406489868843162] -> 0. 22171292045649288

2022-03-29 13. 14. 07,542. DEBUG. nadam. function. derivative[-0. 165955990594852, 0. 4406489868843162] -> [-0. 33191198  0. 88129797]

2022-03-29 13. 14. 07,542. INFO. nadam. iter. Iteration 0 variable 0. mhat=-0. 597442 nhat=0. 110055

2022-03-29 13. 14. 07,542. INFO. nadam. iter. Iteration 0 variable 1. mhat=1. 586336 nhat=0. 775909

2022-03-29 13. 14. 07,542. DEBUG. nadam. function. objective[-0. 12993797816930272, 0. 4046309737819536] -> 0. 18061010311445824

2022-03-29 13. 14. 07,543. INFO. nađam. >0 f[[-0. 12993798  0. 40463097]] = 0. 18061

2022-03-29 13. 14. 07,543. DEBUG. nadam. function. derivative[-0. 12993797816930272, 0. 4046309737819536] -> [-0. 25987596  0. 80926195]

2022-03-29 13. 14. 07,543. INFO. nadam. iter. Iteration 1 variable 0. mhat=-0. 680200 nhat=0. 177413

2022-03-29 13. 14. 07,543. INFO. 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. nađam. function. mục tiêu[-0. 09764011794760165, 0. 3708277653552375] -> 0. 14704682419118062

2022-03-29 13. 14. 07,543. THÔNG TIN. nađam. >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 chức năng đó trong thông báo được ghi bởi bộ ghi nhật ký logging.basicConfig[]9

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 bạn dễ dàng theo dõi các vấn đề hơn là đánh dấu nhật ký bằng màu sắc bằng mô-đun %[asctime]s0. Bạn cần cài đặt mô-đun trước

1

pip cài đặt colorama

Dưới đây là ví dụ về cách bạn có thể sử dụng mô-đun %[asctime]s0 với mô-đun %[asctime]s2 để thay đổi màu nhật ký và độ sáng của văn bản

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ý. DEBUG]

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ý. debug['Debug message']

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 + 'Warning message']

nhật ký. lỗi[Trước. VÀNG + Kiểu dáng. BRIGHT + 'Error message']

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

where the %[asctime]s3, %[asctime]s4, and %[asctime]s5 from the %[asctime]s0 module control the foreground, background, and brightness style of the text printed. This is leveraging the ANSI escape characters and works only on ANSI-supported terminals. Hence this is not suitable for logging to a text file

In fact, we may derive the print[]4 class with

1

2

3

4

5

6

7

8

9

. . .

colors = {"DEBUG". Fore. BLUE, "INFO". Fore. CYAN,

          "WARNING". Fore. YELLOW, "ERROR". Fore. RED, "CRITICAL". Fore. MAGENTA}

class ColoredFormatter[logging. Formatter].

    def format[self, record].

        msg = logging. Formatter. format[self, record]

        if record. tên cấp độ trong màu sắc.

            msg = colors[record. levelname] + msg + Fore. RESET

        return msg

and use this instead of %[asctime]s8. The following is how we can further modify the Nadam example to add color

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

# gradient descent optimization with nadam for a two-dimensional test function

nhập ghi nhật ký

nhập colorama

từ colorama nhập Fore

 

from math import sqrt

từ numpy nhập asarray

from numpy. ngẫu nhiên nhập ranh giới

từ numpy. ngẫu nhiên nhập hạt

 

def loggingdecorator[name].

    logger = logging. getLogger[name]

    def _decor[fn].

        function_name = 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. items[]]

            logger. debug["%s[%s] -> %s", function_name, ", ". join[argstr], ret]

            return ret

        return _fn

    return _decor

 

# hàm mục tiêu

@loggingdecorator["nadam. function"]

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. function"]

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 = bounds[. , 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.shape[0]]]

    # chạy giảm độ dốc

    cho t trong phạm vi[n_iter]:

        iterlogger = ghi nhật ký. getLogger["nadam. iter"]

        # calculate gradient g[t]

        g = đạo hàm[x[0], x[1]]

        # xây dựng giải pháp cho từng biến một

        cho i trong phạm vi[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]] . 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

            iterlogger. thông tin["Lặp %d biến %d. mhat=%f nhat=%f", t, i, mhat, nhat]

        # evaluate candidate point

        điểm = mục tiêu[x[0], x[1]]

        # tiến trình báo cáo

        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". Fore. BLUE, "INFO". Fore. CYAN,

          "WARNING". Fore. YELLOW, "ERROR". Fore. RED, "CRITICAL". Fore. MAGENTA}

class ColoredFormatter[logging. Formatter].

    def format[self, record].

        msg = logging. Formatter. format[self, record]

        if record. tên cấp độ trong màu sắc.

            msg = colors[record. levelname] + msg + Fore. RESET

        return msg

 

# 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ý. DEBUG]

logger = logging. getLogger["nadam. iter"]

nhật ký. setLevel[ghi nhật ký. DEBUG]

# 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], [-1. 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

best, score = 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ã

Làm cách nào để thêm trình xử lý vào trình ghi Python?

setFormatter[formatter] # thêm trình xử lý vào nhật ký trình ghi nhật ký gốc. getLogger['']. addHandler[console] # Bây giờ, chúng ta có thể đăng nhập vào trình ghi nhật ký gốc hoặc bất kỳ trình ghi nhật ký nào khác.

Ghi nhật ký getLogger [__ Tên __] Python là gì?

getLogger[name] thường được thực thi. Hàm getLogger[] chấp nhận một đối số duy nhất - tên của trình ghi nhật ký. Nó trả về một tham chiếu đến một phiên bản trình ghi với tên được chỉ định nếu được cung cấp hoặc gốc nếu không . Nhiều lệnh gọi getLogger[] có cùng tên sẽ trả về một tham chiếu đến cùng một đối tượng logger.

Trình xử lý trong Django là gì?

Trình xử lý. Trình xử lý là công cụ xác định điều gì sẽ xảy ra với từng thông báo trong trình ghi nhật ký . Nó mô tả một hành vi ghi nhật ký cụ thể, chẳng hạn như viết một tin nhắn lên màn hình, vào một tệp hoặc vào một ổ cắm mạng. Giống như trình ghi nhật ký, trình xử lý cũng có cấp nhật ký.

Chủ Đề