Tệp nhật ký tập lệnh python

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

Logging in Python
Photo by ilaria88. Some rights reserved

Tutorial Overview

This tutorial is divided into four parts; they are

  • The benefits of logging
  • Basic logging
  • Advanced configuration to logging
  • An example of the use of logging

Benefits of Logging

You may ask. “Why not just use printing?”

When you run an algorithm and want to confirm it is doing what you expected, it is natural to add some print[] statements at strategic locations to show the program’s state. Printing can help debug simpler scripts, but as your code gets more and more complex, printing lacks the flexibility and robustness that logging has

With logging, you can pinpoint where a logging call came from, differentiate severity between messages, and write information to a file, which printing cannot do. For example, we can turn on and off the message from a particular module of a larger program. We can also increase or decrease the verbosity of the logging messages without changing a lot of code

Basic Logging

Python has a built-in library, logging, for this purpose. It is simple to create a “logger” to log messages or information that you would like to see

The logging system in Python operates under a hierarchical namespace and different levels of severity. The Python script can create a logger under a namespace, and every time a message is logged, the script must specify its severity. The logged message can go to different places depending on the handler we set up for the namespace. The most common handler is to simply print on the screen, like the ubiquitous print[] function. When we start the program, we may register a new handler and set up the level of severity to which the handler will react

There are 5 different logging levels that indicate the severity of the logs, shown in increasing severity

  1. DEBUG
  2. INFO
  3. WARNING
  4. ERROR
  5. CRITICAL

A very simple example of logging is shown below, using the default logger or the root logger

1

2

3

4

5

6

7

import logging

 

logging. debug['Debug message']

logging. info['Info message']

logging. warning['Warning message']

logging. error['Error message']

logging. critical['Critical message']

These will emit log messages of different severity. While there are five lines of logging, you may see only three lines of output if you run this script, as follows

1

2

3

CẢNH BÁO. root. This is a warning message

ERROR. root. This is an error message

CRITICAL. root. This is a critical message

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

import logging

 

logging. basicConfig[filename = 'file. log',

                    level = logging. DEBUG,

                    format = '%[asctime]s. %[levelname]s. %[name]s. %[message]s']

 

logging. debug['Debug message']

logging. info['Info message']

logging. warning['Warning message']

logging. error['Error message']

logging. critical['Critical message']

Running this script will produce no output to the screen but will have the following in the newly created file file.log

1

2

3

4

5

2022-03-22 20. 41. 08,151. DEBUG. root. Debug message

2022-03-22 20. 41. 08,152. INFO. root. Info message

2022-03-22 20. 41. 08,152. WARNING. nguồn gốc. Warning message

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] được sử dụng để định dạng đầu ra

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

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 “_______7_______” được tạo cũng như một bộ ghi có tên "parent" ngầm định

Khi tạo, một bộ ghi con có tất cả các thuộc tính của bộ ghi cha cho đến khi được cấu hình lại. Chúng ta có thể chứng minh điều này với ví dụ sau

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import logging

 

# Tạo `cha mẹ. con` logger

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

 

# Phát ra thông báo tường trình ở mức INFO, theo mặc định, thông báo này không được in ra màn hình

nhật ký. thông tin["đây là cấp độ thông tin"]

 

# Tạo logger `cha mẹ`

parentlogger = ghi nhật ký. 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[]

trình xử lý. setFormatter[ghi nhật ký. Trình định dạng["%[asctime]s. %[name]s. %[tên cấp độ]s. %[tin nhắn]s"]]

parentlogger. setLevel[ghi nhật ký. THÔNG TIN]

parentlogger. addHandler[trình xử lý]

 

# Để bộ ghi nhật ký con gửi lại thông điệp nhật ký

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 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 parent vì nếu không, cấu hình của trình ghi gốc sẽ chiếm ưu thế và không có thông báo nào ở cấp INFO sẽ được in

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ừ logging,0 bởi vì không có trình xử lý nào được chỉ định cho trình ghi nhật ký này. Trên thực tế, cũng không có trình xử lý nào cho trình ghi nhật ký gốc trừ khi bạn thiết lập một trình xử lý với logging.basicConfig[]

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 logging,2, bộ ghi sẽ xuất ra thiết bị đầu cuối, trong khi với logging,3, bộ ghi sẽ xuất ra một tệp cụ thể

Đâ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

import logging

 

# 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 logging,3 được tạo bởi logging.basicConfig[] cho trình ghi 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 đứa trẻ. Chúng ta có thể thấy rằng các bản ghi vào thiết bị đầu cuối bao gồm các thông báo cấp INFO trở lên

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 print[]4. Nhật ký của file.log, tuy nhiên, đã 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

import logging

 

# 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 độ 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

Tin nhắn cảnh báo

Thông báo lỗi

thông điệp quan trọng

trong khi đó của file.log vẫn 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. Each handler’s level will determine if this particular handler should honor this message

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

import logging

 

# 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']

First, we create a formatter, then set our handler to use that formatter. If we wanted to, we could make several different loggers, handlers, and formatters so that we could mix and match based on our preferences

In this example, the file.log0 will have

1

2

3

2022-03-23 13. 28. 31,302. WARNING. Warning message

2022-03-23 13. 28. 31,302. ERROR. Error message

2022-03-23 13. 28. 31,303. CRITICAL. Critical message

and the file.log associated with the handler at root logger will have

1

2

3

4

2022-03-23 13. 28. 31,302. INFO. parent. Info message

2022-03-23 13. 28. 31,302. WARNING. parent. Warning message

2022-03-23 13. 28. 31,302. ERROR. cha mẹ. Error message

2022-03-23 13. 28. 31,303. CRITICAL. parent. Critical message

Below is the visualization of the flow of loggers, handlers, and formatters from

Flow chart of loggers and handlers in the logging module

An Example of the Use of Logging

Let’s consider the Nadam algorithm as an example

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]

 

# khởi tạo 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 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à chỉ định một logging,2

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

.. .

 

import logging

 

.. .

 

# 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. %[tin nhắn]s"]]

nhật ký. addHandler[trình xử lý]

nhật ký. setLevel[ghi nhật ký. GỠ LỖI]

# khởi tạo trình tạo số giả ngẫu nhiên

hạt[1]

. . . # rest of the code

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. At the end of each outer for-loop in file.log9, we replaced the print[] function with logging.basicConfig[]3 so the message will be handled by the logging system

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

    # Create a logger

    logger = logging. getLogger["nadam"]

    # generate an initial point

    x = bounds[. , 0] + rand[len[bounds]] * [bounds[. , 1] - bounds[. , 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 = derivative[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

import logging

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

    logger = logging. getLogger["nadam"]

    # generate an initial point

    x = bounds[. , 0] + rand[len[bounds]] * [bounds[. , 1] - bounds[. , 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 = derivative[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. %[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[logging. INFO]

# khởi tạo 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, file.log7 and logging.basicConfig[]5, and set them in different levels. In the inner loop of file.log9, we use the child logger to print some internal variables. 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. Lặp lại 1 biến 0. mhat=-0. 680200 nhat=0. 177413

2022-03-29 12. 24. 59,421. 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 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 logging.basicConfig[]7 và 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

.. .

 

# 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ý 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 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 %[asctime]s0. Bạn cần cài đặt mô-đun trước

1

pip cài đặt colorama

Here’s an example of how you can use the %[asctime]s0 module with the %[asctime]s2 module to change your log colors and text brightness

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import logging

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 đó %[asctime]s3, %[asctime]s4 và %[asctime]s5 từ mô-đun %[asctime]s0 điều khiển kiểu nền trước, nền sau và độ sáng của văn bản được in. Điều này đang tận dụng các ký tự thoát ANSI và chỉ hoạt động trên các thiết bị đầu cuối được ANSI hỗ trợ. Do đó, điều này không phù hợp để đăng nhập vào tệp văn bản

Trên thực tế, chúng ta có thể dẫn xuất lớp print[]4 với

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 %[asctime]s8. Sau đây là cách chúng ta có thể sửa đổi thêm ví dụ Nadam để thêm màu

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

import logging

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

    logger = logging. getLogger["nadam"]

    # generate an initial point

    x = bounds[. , 0] + rand[len[bounds]] * [bounds[. , 1] - bounds[. , 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 = derivative[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[" . %[levelname]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]

# khởi tạo 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

Note that the colorful output can help us spot any abnormal behavior easier. 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ã

Chủ Đề