Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Bài viết được sự cho phép của tác giả Kien Dang Chung

Video trong bài viết

Chúng ta có quy trình 3 bước để máy có thể học nhưng trước khi đi đến phần thuật toán, tôi muốn giới thiệu với các bạn một chút về môi trường chúng ta sẽ thực hành viết code Python.

Tham khảo: Jupyter Notebook, công cụ không thể thiếu khi học Python. Bài viết này coi như bạn đã có biết cách sử dụng Jupyter Notebook.

  Vẽ đồ thị trong Python với thư viện Matplotlib
  "Code dễ đọc" là như thế nào?

1. Markdown và LaTex trong Jupyter Notebook

Jupyter Notebook là công cụ thực hiện code Python, không những thế bạn có thể đưa vào văn bản, hình ảnh giúp cho các đoạn code dễ hiểu và có thể chia sẻ với mọi người.

Phần văn bản của Jupyter Notebook có thể đưa vào nội dung rất phong phú với các cú pháp Markdown và LaTex:

  • Markdown là một cú pháp sẽ được phân tích cú pháp thành HTML, nó có thể đưa vào tất các các phần tử của HTML, do đó Notebook của bạn sẽ không khác gì một trang web cả.
  • LaTex là công cụ đánh dấu và hiển thị cho các công thức toán học và khoa học. Bạn thử xem hai hàm số này, cái nào dễ nhìn hơn: y = x^2 + 2x + 1 và y=x2+2x+1y=x2+2x+1.

Trang web bạn đang xem All Laravel được chúng tôi xây dựng trên nền tảng OctoberCMS cũng đang sử dụng các công cụ như Markdown và LaTex để biên soạn nội dung các bài viết mà bạn đang xem.

1.1 Cú pháp Markdown

Có khá nhiều cú pháp trong Markdown nhưng tôi sẽ giới thiệu sơ qua một số cú pháp hay dùng nhất:

Tiêu đề: Trong HTML chúng ta có các thẻ tiêu đề từ H1 đến H6 thì trong Markdown, chúng ta thực hiện định dạng một câu thành tiêu đề bằng dấu # ở trước. Ví dụ:

# Đây là tiêu đề H1 
nó sẽ tương ứng với 
<h1>Đây là tiêu đề H1</h1>

Muốn có tiêu đề H2 chúng ta sử dụng hai dấu ##, H3 tương ứng với ###…

Định dạng văn bản: Một số định dạng phổ biến như viết đậm, viết nghiêng trong Markdown sẽ như sau:

**Đoạn này chữ đậm** 
nó sẽ tương ứng với 
<strong>Đoạn này chữ đậm</strong>

*Đoạn này chữ nghiêng*
nó sẽ tương ứng với 
<em>Đoạn này chữ đậm</em>

Danh sách: Có hai loại danh sách là danh sách có thứ tự với số ở đầu (ol) và danh sách không có thứ tự (ul). Trong Markdown các danh sách được viết khá dễ dàng:

* Python
* C#
* PHP

Tương đương với

<ul>
    <li>Python</li>
    <li>C#</li>
    <li>PHP</li>
</ul>

Kết quả thực tế như sau:

  • Python
  • C#
  • PHP

Tương tự với danh sách có thứ tự, chúng ta chỉ cần viết như khi đánh văn bản hay dùng:

1. Python
2. C#
3. PHP

Tương đương với

<ol>
    <li>Python</li>
    <li>C#</li>
    <li>PHP</li>
</ol>

Kết quả thực tế như sau:

  1. Python
  2. C#
  3. PHP

Có rất nhiều các cú pháp trong Markdown, bạn có thể tìm hiểu thêm trên mạng với từ khóa Markdown syntax, ở đây tôi chỉ giới thiệu để bạn hiểu được Markdown là gì? Bản chất Markdown là một ngôn ngữ đánh dấu trung gian, nó khá tiện dụng khi viết nội dung đặc biệt với các tài liệu khoa học. Các hệ thống hỗ trợ Markdown sẽ thực hiện theo thứ tự như sau:

Markdown -> HTML -> Hiển thị nội dung cho người dùng.

1.2 Cú pháp LaTex

LaTex nhận dạng nội dung bên trong một đoạn văn bản là công thức hay không thông qua thẻ $ và $$.

  • Với $, nội dung bên trong sẽ là biểu thức nằm trên cùng một dòng với văn bản ở ngoài.
  • Với $$ nội dung bên trong là biểu thức sẽ được trình bày ở giữa một dòng mới.

Ví dụ: Phương trình hàm parabol y=3x2+2x+1y=3×2+2x+1 là dạng cùng dòng (inline) với thẻ $ trong LaTex. Nhưng biểu thức sau đây lại sử dụng $$:

i=0ni2=(n2+n)(2n+1)6∑i=0ni2=(n2+n)(2n+1)6

Chỉ số trên và chỉ số dưới: sử dụng _ cho chỉ số dưới và ^ cho chỉ số trên. Ví dụ: $x^2$ sẽ có kết quả là x2x2, $n_i$ sẽ có kết quả là nini và kết hợp cả hai $\theta_0^{(i)}$ sẽ cho kết quả là θ(i)0θ0(i). Các biểu thức toán sẽ rất đẹp phải không bạn.

Tổng, tích phân: Với tổng chúng ta sử dụng \sum, tích phân là \int với các chỉ số trên và chỉ số dưới giống như ở phần trên. Ví dụ: $\sum_{i=0}^ni^2$ cho kết quả ni=0i2∑i=0ni2. Ví dụ khác về tích phân $$\int_0^{\frac{\pi}{4}}\sqrt{1-x^2}dx$$ cho kết quả

π401x2−−−−−√dx∫0π41−x2dx

Phân số: Phân số trong LaTex sử dụng cú pháp $\frac{a}{b}$, ví dụ $\frac{(n^2+n)(2n+1)}{6}$ cho kết quả (n2+n)(2n+1)6(n2+n)(2n+1)6.

Trên đây là một số cú pháp cơ bản khi biểu diễn các biểu thức toán học với LaTex, bạn có thể xem nhiều các công thức toán học khác có thể được biểu diễn bằng LaTex ở đây.

1.3 Đệ nhất lẩu Jupyter, Markdown và LaTex

Với sự kết hợp của Markdown và LaTex chúng ta có thể biểu diễn các thuật toán với các biểu thức toán học kết hợp với các nội dung diễn giải tuyệt vời. Không chỉ có vậy, Jupyter Notebook là một tài liệu có chứa cả các cell có code Python có thể thực thi được, bạn thấy đấy, giờ đây chúng ta chỉ cần 1 chỗ vừa có thể xem các diễn giải các công thức và dưới đó là các phần code thực hiện và xem các kết quả chương trình đưa ra. Có thể nói ĐỆ NHẤT LẨU JML (Jupyter-Markdown-LaTex) đã mang lại cho chúng ta những lồi nẩu cực cực cực … cực kỳ hấp dẫn.

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

2. Vẽ đồ thị trong Python

Các cụ nhà ta có câu:

Trăm nghe không bằng một thấy.

Cho thấy tầm quan trọng của việc biểu diễn dữ liệu bằng các biểu đồ, đồ thị. Trong phần này, chúng ta sẽ thực hiện vẽ đồ thị các hàm số trong Python, nó giúp cho các thuật toán lằng nhằng có thể được diễn tả bằng hình ảnh một cách dễ hiểu nhất.

Trong hệ sinh thái Python, có rất nhiều các thư viện bên thứ 3 được phát triển dưới dạng mã nguồn mở, rất phổ biến và cực hữu ích khi làm việc với Python. Trong phần này tôi giới thiệu với bạn hai thư viện được dùng khá nhiều trong Khóa học Machine Learning này đó là Numpy và Matplotlib.

  • Numpy: giúp thao tác với các mảng đa chiều, sinh dữ liệu và thực hiện các phép biến đổi dữ liệu dễ dàng hơn.
  • Matplotlib: thư viện giúp bạn mô phỏng dữ liệu thành các biểu đồ, đồ thị, thư viện không thể thiếu khi bạn thực hiện phân tích dữ liệu.

Nói thì nghe cao siêu vậy thôi, chúng ta cùng bắt tay vào một ví dụ vẽ đồ thị, bạn sẽ thấy các thư viện này rất dễ sử dụng. Trong bài trước, bạn đã nghe đến khái niệm về hàm chi phí hay hàm mất mát (từ giờ tôi sẽ chỉ dùng tên gọi Hàm chi phí), đó là cơ sở để tính toán các sai lệch khi đưa ra các giá trị khởi tạo trong bước 1 của Quy trình 3 bước trong Machine Learning. Chúng ta cần vẽ đồ thị của hàm chi phí để có thể tìm được các điểm cực tiểu mà tại đó là lời giải của thuật toán Grandient Descent.

2.1 Phương thức plot()

Giả sử chúng ta có một hàm chi phí y=x2+x+1y=x2+x+1, chúng ta sẽ vẽ hàm chi phí này để có thể tìm hiểu về điểm cực tiểu, nơi mà chi phí thấp nhất (Chi phí – cost, ở đây không có nghĩa là mất mát về tiền, chi phí ở đây với ý nghĩa là …). Bắt đầu thôi:

Đầu tiên, chúng ta thực hiện import các thư viện cần thiết:

import matplotlib.pyplot as plt
import numpy as np

%matplotlib inline

Hai dòng đầu tiên là import các thư viện matplotlib và numpy, dòng %matplotlib inline là một câu lệnh của Jupyter Notebook, nó giúp vẽ các đồ thị bên trong các cell. Tiếp đó, để vẽ được hàm y=x2+x+1y=x2+x+1 chúng ta sẽ sử dụng phương thức plot() của pyplot là một module trong matplotlib mà ta đã đặt tên ngắn gọn là plt.

Phương thức plot() giúp vẽ một danh sách các điểm thành một đồ thị, phương thức này có nhiều tham số nhưng chúng ta chỉ quan tâm đến tham số x và y là hai danh sách (Python List) với giá trị là tọa độ x và y.

Ví dụ:

x_list = [0,2,7]
y_list = [1,8,9]

plt.plot(x_list, y_list)
plt.show()

Kết quả khi thực thi chúng ta có đồ thị như sau:

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Chú ý, phương thức plot() trả về một đối tượng Python do đó để thực sự vẽ ra đồ thị, chúng ta cần gọi phương thức show().

2.2 Tạo dữ liệu mẫu với numpy

Bạn thấy đấy, chúng ta có 3 điểm là (0,1) (2,8) và (7,9), ở đây chúng ta đưa hết giá trị trên tọa độ x vào biến x_list và trên tọa độ y vào y_list. plot() đã vẽ ra ba điểm này và giữa hai điểm liên tiếp nó vẽ một đường thẳng. Ok, vậy chúng ta có thể vẽ phương trình y=x2+x+1y=x2+x+1 như thế nào? Chẳng lẽ chúng ta phải tự tạo ra dữ liệu là danh sách các tọa độ x, y này, như thế thì thật mất nhiều công sức, chưa kể là giữa hai điểm ở đây là một đường thẳng, như vậy đồ thị vẽ ra cũng không trơn tru vì chỉ là một đường nối các điểm với nhau.

Không có vấn đề gì, chúng ta vẫn còn Numpy, bạn nhớ chứ, chúng ta đã import thư viện này vào nhưng chưa sử dụng đến. Trong numpy có phương thức linspace() cho phép tạo ra một mảng số với số lượng phần tử cho trước và nằm trong một phạm vi cho trước.

x_1 = np.linspace(start=-3, stop=3, num=100)

Dòng code này sẽ tạo ra một mảng gồm 100 phần tử chạy trong khoảng [-3,3] với giá trị các phần tử cách đều nhau.

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

2.3 Vẽ đồ thị hàm parabol

Ok, chúng ta đã tạo ra được dữ liệu mẫu cho trục x trong khoảng từ [-3, 3], giờ là lúc cần định nghĩa hàm y=x2+x+1y=x2+x+1 trong Python và tính ra các giá trị cho trục y tương ứng với các giá trị trục x.

def f(x):
    return x**2 + x + 1
y_1 = f(x_1)

Kết quả ta có biến y_1 là một mảng các giá trị hàm số y=x2+x+1y=x2+x+1 tương ứng với x tại các giá trị trong mảng x_1.

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Ok, dữ liệu cho các trục x, y đã chuẩn bị xong, giờ chúng ta sẽ vẽ đồ thị y=x2+x+1y=x2+x+1.

plt.plot(x_1, y_1)
plt.show()

Kết quả chúng ta có đồ thị y=x2+x+1y=x2+x+1 như hình dưới đây:

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

Đồ thị đã rất đẹp, nhưng chúng ta vẫn cần định dạng lại chút, ví dụ thêm nhãn cho các trục tọa độ, giới hạn tọa độ hiển thị:

plt.xlim(-3, 3)
plt.ylim(0, 8)
plt.xlabel('X', fontsize=16)
plt.ylabel('f(x)', fontsize=16)
plt.plot(x_1, y_1)
plt.show()

Trong đoạn code trên, xlim() và ylim() để giới hạn vùng tọa độ sẽ hiển thị trên trục x và y, xlabel() và ylabel() để gán nhãn cho các trục tọa độ, kết quả chúng ta được đồ thị mới như sau:

Tạo dữ liệu và vẽ đồ thị với Numpy và Matplotlib

2.4 Vài lời tâm sự

Đồ thị hàm parabol y=x2+x+1y=x2+x+1 rất đẹp được vẽ lên từ 100 điểm nối với nhau. Chúng ta thấy đường parabol rất trơn tru vì trong một khoảng ngắn có tới 100 điểm thì các điểm gần như sát với nhau do đó chúng ta không cảm nhận được những đoạn thẳng nối từng hai điểm liên tiếp.

Bạn sẽ đặt câu hỏi, tại sao tôi chọn khoảng [-3, 3] để vẽ đồ thị, thực ra khi vẽ chúng ta sẽ phải dò dẫm chút, đưa ra một khoảng bất kỳ và chỉnh dần về khoảng sao cho đồ thị có những điểm đặc biệt nằm chọn trong đó. Khi vẽ bạn cũng chọn số điểm vừa phải, nếu thấy chưa trơn tru thì tăng dần lên tránh việc máy tính phải tính toán nhiều, đó là thói quen cần thiết của những người làm về khoa học dữ liệu.

Một thực tế nữa là khi làm việc với data science, chúng ta chỉ luôn tính xấp xỉ chứ không thể có những con số tuyệt đối như khi học toán học. Những con số xấp xỉ đã có một giá trị rất cao mặc dù nếu khi thi toán, giải kết quả xấp xỉ là bạn bị điểm 0 liền. Ví dụ, khi tính toán một phương án đầu tư, chỉ cần cho kết quả cỡ 60-70% là đã coi như 100% chứ không như trong toán, lúc nào cũng phải 1+1=21+1=2.

3. Bài tập

Nhân tiện về chủ đề vẽ đồ thị và khảo sát hàm số, một chủ đề rất thích hợp với chương trình toán trong Phổ thông trung học. Mình đưa ra một số bài tập ở đây để mọi người vẽ và hồi tưởng về một thời mài đít quần trên ghế nhà trường :D.

Bài tập: Soạn một notebook trên Jupyter bao gồm cả đề bài, vẽ đồ thị với Python.

Cho đồ thị hàm số y=14x332x2+5y=14×3−32×2+5

  1. Khảo sát sự biến thiên, vẽ đồ thị đã cho.
  2. Tìm giá trị của m để phương trình x36x2+m=0x3−6×2+m=0 có 3 nghiệm phân biệt.

Hehe, giải kiểu gì cũng được nhé, miễn là ra kết quả, kể cả kết quả gần đúng. Lời giải có trong bài tiếp theo nhé.

Bài viết gốc được đăng tải tại allaravel.com

Có thể bạn quan tâm:

Xem thêm Việc làm Developer hấp dẫn trên TopDev