結合scipy.linalg在Python中使用線性系統

華為雲開發者社群發表於2021-08-20
摘要:將線性代數概念應用到實際問題中scipy.linalg 使用 Python 和 NumPy處理向量和矩陣 使用線性系統模擬實際問題 使用求解線性系統 scipy.linalg

本文分享自華為雲社群《使用scipy.linalg在Python中使用線性系統》,作者:Yuchuan。

線性代數廣泛應用於各種學科,一旦您使用向量線性方程等概念組織資訊,您就可以用它來解決許多問題。在Python中,與該主題相關的大多數例程都在中實現scipy.linalg,它提供了非常快速的線性代數功能。

尤其是,線性系統在模擬各種現實世界問題中發揮著重要作用,並scipy.linalg提供了以有效方式研究和解決這些問題的工具。

在本教程中,您將學習如何:

  • 將線性代數概念應用到實際問題中scipy.linalg
  • 使用Python和NumPy處理向量和矩陣
  • 使用線性系統模擬實際問題
  • 如何使用線性系統求解scipy.linalg

讓我們開始吧!

入門scipy.linalg

SciPy是一個用於科學計算的開源Python庫,包括用於科學和工程中常見任務的幾個模組,例如線性代數、優化、積分、插值和訊號處理。它是SciPy堆疊的一部分,其中包括其他幾個用於科學計算的包,例如NumPy、Matplotlib、SymPy、IPython和pandas。

線性代數是數學的一個分支,涉及線性方程及其使用向量和矩陣的表示。它是用於多個工程領域的基礎學科,也是深入瞭解機器學習的先決條件。

scipy.linalg包括用於處理線性代數問題的多種工具,包括用於執行矩陣計算的函式,例如行列式、逆矩陣、特徵值、特徵向量和奇異值分解。

在本教程中,您將使用from的一些函式scipy.linalg來解決涉及線性系統的實際問題。為了使用scipy.linalg,您必須安裝和設定SciPy庫,您可以使用AnacondaPython發行版和conda包和環境管理系統來完成。

注意:要了解有關Anaconda和conda的更多資訊,請檢視在Windows上設定Python進行機器學習。

首先,建立一個conda環境並啟用它:

$condacreate--namelinalg
$condaactivatelinalg

啟用conda環境後,您的提示將顯示其名稱linalg.然後你可以在環境中安裝必要的包:

(linalg)$condainstallscipyjupyter

執行此命令後,系統應該需要一段時間才能確定依賴項並繼續安裝。

注意:除了SciPy,您還將使用JupyterNotebook在互動式環境中執行程式碼。這樣做不是強制性的,但它有助於處理數值和科學應用程式。

有關使用JupyterNotebooks的複習,請檢視JupyterNotebook:簡介。

如果您更喜歡使用不同的Python發行版和pip包管理器來閱讀本文,請展開下面的可摺疊部分以瞭解如何設定您的環境。

設定環境使用pip顯示隱藏

在開啟JupyterNotebook之前,您需要註冊condalinalg環境,以便您可以使用它作為核心來建立Notebook。為此,在linalg啟用環境的情況下,執行以下命令:

(linalg)$python-mipykernelinstall--user--namelinalg

現在您可以通過執行以下命令開啟JupyterNotebook:

$jupyternotebook

在瀏覽器中載入Jupyter後,通過點選建立一個新的膝上型電腦新→linalg,如下圖所示:

結合scipy.linalg在Python中使用線性系統

內的膝上型電腦,你可以測試是否安裝成功通過匯入的scipy包:

>>>

In[1]:importscipy

現在您已經完成了環境的設定,您將看到如何在Python中使用向量和矩陣,這是使用scipy.linalg線性代數應用程式的基礎。

使用NumPy處理向量和矩陣

甲向量是用來表示物理量同時具有大小和方向的數學實體。它是解決工程和機器學習問題的基本工具,就像矩陣一樣,用於表示向量變換等應用程式。

NumPy是Python中處理矩陣和向量最常用的庫,用於處理scipy.linalg線性代數應用程式。在本節中,您將瞭解使用它建立矩陣和向量並對其執行操作的基礎知識。

要開始處理矩陣和向量,您需要在JupyterNotebook中做的第一件事是匯入numpy.通常的方法是使用別名np:

>>>

In[2]:importnumpyasnp

為了表示矩陣和向量,NumPy使用一種稱為ndarray.

要建立ndarray物件,您可以使用np.array(),它需要一個類似陣列的物件,例如列表或巢狀列表。

例如,假設您需要建立以下矩陣:

結合scipy.linalg在Python中使用線性系統

要使用NumPy建立它,您可以使用np.array(),提供一個包含矩陣每一行元素的巢狀列表:

>>>

In[3]:A=np.array([[1,2],[3,4],[5,6]])
...:A
Out[3]:
array([[1,2],
[3,4],
[5,6]])

您可能會注意到,NumPy提供了矩陣的視覺化表示,您可以在其中識別其列和行。

值得注意的是,NumPy陣列的元素必須是相同型別的。您可以使用以下方法檢查NumPy陣列的型別.dtype:

>>>

In[4]:A.dtype
Out[4]:
dtype('int64')

由於的所有元素A都是整數,因此陣列是用type建立的int64。如果元素之一是float,則將使用type建立陣列float64:

In[5]:A=np.array([[1.0,2],[3,4],[5,6]])
...:A
Out[5]:
array([[1.,2.],
[3.,4.],
[5.,6.]])

In[6]:A.dtype
Out[6]:
dtype('float64')

要檢查ndarray物件的尺寸,您可以使用.shape.例如,要檢查的尺寸A,您可以使用A.shape:

>>>

In[7]:A.shape
Out[7]:
(3,2)

正如預期的那樣,A矩陣的維度是3×2因為A有三行和兩列。

在處理涉及矩陣的問題時,您通常需要使用轉置操作,它交換矩陣的列和行。

要轉置由ndarray物件表示的向量或矩陣,您可以使用.transpose()或.T。例如,你可以得到的轉A用A.T:

In[8]:A.T
Out[8]:
array([[1.,3.,5.],
[2.,4.,6.]])

通過換位,列A變成了行,A.T行變成了列。

要建立向量,您可以使用np.array(),提供包含向量元素的列表:

>>>

In[9]:v=np.array([1,2,3])
...:v
Out[9]:
array([1,2,3])

要檢查向量的維度,您可以.shape像以前一樣使用:

>>>

In[10]:v.shape
Out[10]:
(3,)

請注意,此向量的形狀是(3,)andnot(3,1)or(1,3)。這是一個NumPy功能,適用於那些習慣使用MATLAB的人。在NumPy中,可以建立一維陣列,例如v,這在執行矩陣和向量之間的操作時可能會導致問題。例如,轉置操作對一維陣列沒有影響。

每當您向提供類似一維陣列的引數時np.array(),生成的陣列將是一維陣列。要建立二維陣列,您必須提供類似二維陣列的引數,例如巢狀列表:

>>>

In[11]:v=np.array([[1,2,3]])
...:v.shape
Out[11]:
(1,3)

在上述例子中,尺寸v是1×3,其對應於一個兩維的線向量的尺寸。要建立列向量,您可以使用巢狀列表:

>>>

In[12]:v=np.array([[1],[2],[3]])
...:v.shape
Out[12]:
(3,1)

在這種情況下,尺寸v為3×1,其對應於一個兩維列向量的尺寸。

使用巢狀列表建立向量可能很費力,尤其是對於使用最多的列向量。作為替代方案,您可以建立一個一維向量,為提供一個平面列表np.array,並用於.reshape()更改ndarray物件的維度:

In[13]:v=np.array([1,2,3]).reshape(3,1)
...:v.shape
Out[13]:
(3,1)

在上面的示例中,您使用從.reshape()形狀(3,1)為的一維向量獲取形狀的列向量(3,)。值得一提的是,.reshape()期望新陣列的元素數與原陣列的元素數相容。換句話說,具有新形狀的陣列中的元素數必須等於原始陣列中的元素數。

在這個例子中,你也可以在.reshape()不明確定義陣列行數的情況下使用:

>>>

In[14]:v=np.array([1,2,3]).reshape(-1,1)
...:v.shape
Out[14]:
(3,1)

在這裡,-1您提供的引數.reshape()表示新陣列只有一列所需的行數,如第二個引數所指定。在這種情況下,由於原始陣列具有三個元素,因此新陣列的行數將為3。

在實際應用中,您經常需要建立零、一或隨機元素的矩陣。為此,NumPy提供了一些方便的函式,接下來您將看到這些函式。

使用便捷函式建立陣列

NumPy還提供了一些方便的函式來建立陣列。例如,要建立一個填充零的陣列,您可以使用np.zeros():

>>>

In[15]:A=np.zeros((3,2))
...:A
Out[15]:
array([[0.,0.],
[0.,0.],
[0.,0.]])

作為它的第一個引數,np.zeros()需要一個元組來指示您要建立的陣列的形狀,它返回一個型別為的陣列float64。

同樣,要建立填充陣列,您可以使用np.ones():

>>>

In[16]:A=np.ones((2,3))
...:A
Out[16]:
array([[1.,1.,1.],
[1.,1.,1.]])

值得注意的是,np.ones()它還返回一個型別為的陣列float64。

要建立具有隨機元素的陣列,您可以使用np.random.rand():

In[17]:A=np.random.rand(3,2)
...:A
Out[17]:
array([[0.8206045,0.54470809],
[0.9490381,0.05677859],
[0.71148476,0.4709059]])

np.random.rand()返回一個包含從0到的隨機元素的陣列1,取自均勻分佈。請注意,與np.zeros()and不同np.ones(),np.random.rand()它不期望元組作為其引數。

同樣,要從均值和單位方差為零的正態分佈中獲取隨機元素的陣列,您可以使用np.random.randn():

>>>

In[18]:A=np.random.randn(3,2)
...:A
Out[18]:
array([[-1.20019512,-1.78337814],
[-0.22135221,-0.38805899],
[0.17620202,-2.05176764]])

現在您已經建立了陣列,您將看到如何使用它們執行操作。

對NumPy陣列執行操作

在陣列上使用加法(+)、減法(-)、乘法(*)、除法(/)和指數(**)運算子的常見Python運算始終按元素執行。如果運算元之一是標量,則將在標量和陣列的每個元素之間執行操作。

例如,為了建立填充元素的矩陣等於10,則可以使用np.ones()由和乘法的輸出10使用*:

>>>

In[19]:A=10*np.ones((2,2))
...:A
Out[19]:
array([[10.,10.],
[10.,10.]])

如果兩個運算元都是相同形狀的陣列,則將在陣列的對應元素之間執行操作:

>>>

In[20]:A=10*np.ones((2,2))
...:B=np.array([[2,2],[5,5]])
...:C=A*B
...:C
Out[20]:
array([[20.,20.],
[50.,50.]])

在這裡,您將matrixA的每個元素乘以matrix的相應元素B。

要根據線性代數規則執行矩陣乘法,您可以使用np.dot():

>>>

In[21]:A=np.array([[1,2],[3,4]])
...:v=np.array([[5],[6]])
...:x=np.dot(A,v)
...:x
Out[21]:
array([[17],
[39]])

在這裡,您乘以一個2×2矩陣A,該矩陣由一個名為的2×1向量命名v。

您可以使用@運算子獲得相同的結果,從PEP465和Python3.5開始,NumPy和本機Python都支援該運算子:

>>>

In[22]:A=np.array([[1,2],[3,4]])
...:v=np.array([[5],[6]])
...:x=A@v
...:x
Out[22]:
array([[17],
[39]])

除了處理矩陣和向量的基本操作外,NumPy還提供了一些特定的函式來處理numpy.linalg.但是,對於這些應用程式,它scipy.linalg具有一些優勢,您將在下面看到。

比較scipy.linalg用numpy.linalg

NumPy在numpy.linalg模組中包含一些用於處理線性代數應用程式的工具。但是,除非您不想將SciPy作為依賴項新增到專案中,否則通常最好使用scipy.linalg,原因如下:

  • 由於在解釋官方文件,scipy.linalg包含了所有的功能numpy.linalg再加上一些額外的高階功能,不包括在numpy.linalg。
  • scipy.linalg編譯時始終支援BLAS和LAPACK,這些庫包括用於以優化方式執行數值運算的例程。對於numpy.linalg,BLAS和LAPACK的使用是可選的。因此,根據您安裝NumPy的方式,scipy.linalg函式可能比numpy.linalg.

總之,考慮到科學和技術應用一般沒有關於限制的依賴,它通常是一個好主意,安裝SciPy的和使用scipy.linalg代替numpy.linalg。

在下一節中,您將使用scipy.linalg工具來處理線性系統。您將首先通過一個簡單的示例瞭解基礎知識,然後將這些概念應用於實際問題。

使用scipy.linalg.solve()求解線性系統

線性系統可以成為解決幾個實際和重要問題的有用工具,包括與車輛交通、平衡化學方程式、電路和多項式插值相關的問題。

在本節中,您將學習如何使用scipy.linalg.solve()來求解線性系統。但是在開始編寫程式碼之前,瞭解基礎知識很重要。

瞭解線性系統

線性系統,或者更精確地說,線性方程系統,是一組直線與一組變數方程。以下是與變數x₁、x₂和x₃相關的線性系統示例:

結合scipy.linalg在Python中使用線性系統

這裡有涉及三個變數的三個方程。為了有一個線性系統,值ķ₁...ķ₉和b₁...b₃必須是常數。

當只有兩個或三個方程和變數時,可以手動執行計算、組合方程並找到變數的值。但是,對於四個或更多變數,手動求解線性系統需要相當長的時間,並且經常會出錯。

實際應用通常涉及大量變數,這使得手動求解線性系統是不可行的。幸運的是,有一些工具可以完成這項艱鉅的工作,例如scipy.linalg.solve().

使用scipy.linalg.solve()

SciPy提供scipy.linalg.solve()快速且可靠的方式求解線性系統。要了解它是如何工作的,請考慮以下系統:

結合scipy.linalg在Python中使用線性系統

為了使用scipy.linalg.solve(),您首先需要將線性系統寫為矩陣乘積,如下面的等式所示:

結合scipy.linalg在Python中使用線性系統

請注意,您將在計算矩陣乘積後得出系統的原始方程。scipy.linalg.solve()期望求解的輸入是matrixA和vectorb,您可以使用NumPy陣列定義它們。這樣,您可以使用以下程式碼解決系統問題:

>>>

1In[1]:importnumpyasnp
2...:fromscipy.linalgimportsolve
3
4In[2]:A=np.array(
5...:[
6...:[3,2],
7...:[2,-1],
8...:]
9...:)
10
11In[3]:b=np.array([12,1]).reshape((2,1))
12
13In[4]:x=solve(A,b)
14...:x
15Out[4]:
16array([[2.],
17[3.]])

以下是正在發生的事情的細分:

  • 第1行和第2行匯入NumPynp以及solve()fromscipy.linalg。
  • 第4到9行使用名為的NumPy陣列建立係數矩陣A。
  • 第11行使用名為的NumPy陣列建立獨立項向量b。要使其成為具有兩行的列向量,請使用.reshape((2,1)).
  • 第13行和第14行呼叫solve()求解由A和表徵的線性系統b,結果儲存在中x,並列印出來。請注意solve(),即使原始陣列的所有元素都是整數,也會返回帶有浮點分量的解。

如果將原始方程中的x₁=2和x₂=3替換,則可以驗證這是系統的解。

現在您已經瞭解了使用的基礎知識scipy.linalg.solve(),是時候瞭解線性系統的實際應用了。

解決實際問題:BuildingaMealPlan

通常使用線性系統解決的一類問題是當您需要找到獲得某種混合物所需的元件比例時。下面,您將使用這個想法來制定膳食計劃,混合不同的食物以獲得均衡的飲食。

為此,請考慮均衡飲食應包括以下內容:

  • 170單位維生素A
  • 180單位維生素B
  • 140單位維生素C
  • 180單位維生素D
  • 350單位維生素E

你的任務是找出每種不同食物的數量,以獲得指定數量的維生素。在下表中,您可以根據每種維生素的單位分析1克每種食物的結果:

你的任務是找出每種不同食物的數量,以獲得指定數量的維生素。在下表中,您可以根據每種維生素的單位分析1克每種食物的結果:

結合scipy.linalg在Python中使用線性系統

通過將食物1表示為x₁等,並考慮到您將混合x₁單位的食物1、x2單位的食物2等等,您可以寫出您所攝入的維生素A量的表示式d進入組合。考慮到均衡飲食應包含170個單位的維生素A,您​​可以使用維生素A列中的資料寫出以下等式:

結合scipy.linalg在Python中使用線性系統

對維生素B、C、D和E重複相同的過程,您會得到以下線性系統:

結合scipy.linalg在Python中使用線性系統

要使用scipy.linalg.solve(),您必須獲得係數矩陣A和獨立項向量b,它們由以下給出:

結合scipy.linalg在Python中使用線性系統

現在您只需使用scipy.linalg.solve()來找出數量x₁,…,x₅:

>>>

In[1]:importnumpyasnp
...:fromscipy.linalgimportsolve

In[2]:A=np.array(
...:[
...:[1,9,2,1,1],
...:[10,1,2,1,1],
...:[1,0,5,1,1],
...:[2,1,1,2,9],
...:[2,1,2,13,2],
...:]
...:)

In[3]:b=np.array([170,180,140,180,350]).reshape((5,1))

In[4]:x=solve(A,b)
...:x
Out[4]:
array([[10.],
[10.],
[20.],
[20.],
[10.]])

這表明均衡飲食應包括10食物單位1、食物10單位2、20食物20單位3、食物單位4和10食物單位5。

結論

恭喜!您已經學習瞭如何使用一些線性代數概念以及如何使用scipy.linalg來解決涉及線性系統的問題。您已經看到向量和矩陣可用於表示資料,並且通過使用線性代數概念,您可以對實際問題進行建模並以有效的方式解決它們。

在本教程中,您學習瞭如何:

  • 將線性代數概念應用到實際問題中scipy.linalg
  • 使用Python和NumPy處理向量和矩陣
  • 使用線性系統模擬實際問題
  • 使用求解線性系統scipy.linalg

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章