1. 程式人生 > >Machine Learning機器學習入門

Machine Learning機器學習入門

機器學習簡單介紹

machine learning是從資料中提取知識,是統計學,人工智慧和電腦科學交叉的研究領域。

機器學習演算法是能夠將決策過程自動化的演算法,決策過程是從已知的示例中泛化得到的:

  • 監督學習(supervised learning):使用者將成對的輸入和預期的輸出提供給演算法,演算法找到方法根據給定輸出算出預期輸出
  • 無監督學習(unsupervised learning):只有輸入資料是已知的,沒有為演算法提供輸出資料

machine learning中,可以將資料想象成表格,每一個實體或者每一行為一個sample,每一列即實體的屬性為這個sample的feature。


機器學習常用庫

scikit-learn:
最有名的Python機器學習庫,包含目前最先進的機器學習演算法。它依賴於另外兩個包:NumPy和SciPy,還有一些其他依賴包:
pip install numpy scipy matplotlib ipython scikit-learn pandas
後面簡寫為sklearn


Jupyter Notebook:
可以在瀏覽器中執行程式碼的互動環境,在探索性資料分析方面很有用。


NumPy:
科學計算的基礎包之一,功能包括:多維陣列,高階數學函式(線性代數運算和傅立葉變換),以及偽隨機數生成器。在sklearn中numpy陣列是基本的資料結構,所有資料必須轉換成numpy陣列,陣列的所有元素必須是同一型別。

import numpy as np
x = np.array([[1,2,3],[4,5,6]])
>>>x:
       [[1 2 3]
        [4 5 6]]

SciPy:
SciPy是用於科學計算的函式集合,具有線性代數高階程式,數學函式優化,訊號處理,特殊數學函式和統計分佈等多項功能。 sklearn利用SciPy中的函式集合來實現演算法,這裡對我們最重要的是scipy.sparse,它可以給出稀疏矩陣,即sparse matrice,稀疏矩陣用於儲存一個大部分元素都是0的二維陣列,也是sklearn中除了numpy的另一個數據表達方式。

matplotlib:
matplotlib是主要的科學繪相簿,生成可釋出的視覺化內容,比如折線圖,直方圖,散點圖等,可以使用%matplotlib notebook命令將影象直接顯示在瀏覽器中,還可以提供互動環境。

%matplotlib inline
import matplotlib.pyplot as plt
x = np.linespace(-10, 10, 100) # 建立一個-10到10之間的一個共100個數的數列
y = np.sin(x)
plt.plot(x, y, marker="x") # 繪製一個數組關於另一個數組的折線圖

pandas:
pandas是用於處理和分析資料的庫,基於一種叫DataFrame的資料結構,類似於excel表格,pandas中包含了大量用於修改表格和操作表格的方法,還可以像sql那樣對錶格進行查詢和連線,而且pandas接受各種資料格式,每一列資料的型別都可以完全不一樣。總而言之,pandas的功能及其強大,可以去額外學習它。

import pandas as pd
data = {'Name': ["John", "Anna", "Peter", "Linda"],
        'Location' : ["New York", "Paris", "Berlin", "London"],
        'Age' : [24, 13, 53, 33]
       }
data_pandas = pd.DataFrame(data)
# IPython.display allows "pretty printing" of dataframes
# in the Jupyter notebook
display(data_pandas)

上述程式碼會生成一個美觀的表格。查詢這個表格的方法:
display(data_pandas[data_pandas.Age > 30])


第一個入門machine Learning應用:

這是一個花分類的應用:

現有每朵花的一些資料,即花瓣的長和寬,花萼的長和寬,單位為cm,這些花已經被鑑定為屬於setosa, versicolor, virginica三個品種之一。

目標: 假設我們現在會在野外遇到這三種花,我們需要構造一個ML模型,從已有的資料中學習,從而預測新的野花的品種。因為我們已經sample花的資料和品種,所以這是一個監督學習。

這是一個classification問題,可能的輸出都是一個類別class,資料中的每朵花都是這三個類別之一,所以這是一個三分類的問題。一朵花就是一個數據點,他的品種為標籤label。

由於這些資料是ML和統計學中的一個經典的資料集,所以這個資料集被包含在了sklearn的datasets模組中,所以我們可以直接呼叫這些資料。

from sklearn.datasets import load_iris
iris_dataset = load_iris()  # 這裡返回的是一個bunch物件,類似與字典,裡面是鍵值對
print("Keys of iris_dataset:\n", iris_dataset.keys())
>>>Keys of iris_dataset:
 		dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names', 'filename'])  # descr是資料集的簡要說明

print("Target names:", iris_dataset['target_names'])   #target_name的值是一個數組,裡面是我們要預測的花的品種
>>> Target names: ['setosa' 'versicolor' 'virginica']

print("Feature names:\n", iris_dataset['feature_names'])    #feature_name是一個字串列表,對每一個特徵feature有說明
>>> Feature names:
		 ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']

print("Shape of data:", iris_dataset['data'].shape) #data陣列的形狀shape是sample x feature的數量,永遠遵循這個約定
>>> Shape of data: (150, 4)

print("First five rows of data:\n", iris_dataset['data'][:5])  # 打印出來前五個sample的feature資料
>>> First five rows of data:
			 [[5.1 3.5 1.4 0.2]
			 [4.9 3.  1.4 0.2]
			 [4.7 3.2 1.3 0.2]
			 [4.6 3.1 1.5 0.2]
			 [5.  3.6 1.4 0.2]]

print("Target:\n", iris_dataset['target'])  # target是一維陣列,每朵花對應其中的一個數據,品種被轉換成了0,1,2三個整數。
>>> Target:
		 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
		 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
		 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
		 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
		 2 2]

模型是否適用?–訓練資料與測試資料:
如果我們想使用上面的資料構建一個ML模型,用於預測新測量的花的品種,但是在將模型應用於新的測量資料之前,我們需要知道這個模型是否有效。

但是很不幸的是我們不能將用於構建模型的資料在評估模型上使用,因為我們的模型會知道整個資料集的結果,所以一定會得到正確的預測結果。所以這種模型的記憶能力無法衡量這個模型的泛化generalize 能力。

所以我們必須使用新資料即模型沒有見過的資料來評估模型的效能,那麼我們可以將收集好的資料分為兩部分,一部分用來構建機器學習模型,即訓練資料training data/set。另一部分的資料用來評估模型的效能,即測試資料test data/set。那麼怎麼劃分這些資料呢?sklearn中有train_test_split函式可以打亂資料集並且按照75%為訓練資料,25%為測試資料的方式來拆分資料集,這個比例是可以修改的,但是預設的這個比例是最好的,在機器學習中,資料通常用大寫的X表示,資料對應的標籤用小寫的y表示。

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    iris_dataset['data'], iris_dataset['target'], random_state=0)

檢查資料:
下一步就是檢查資料了,需要觀察資料是否正確。最好的方式是將資料視覺化:

  • 一種方法是繪製散點圖,但是由於螢幕只有兩個維度,所以一次只能繪製兩個feature。
  • 另一種方法是基於上一種方法,即散點矩陣圖,從而可以檢視feature兩兩之間的關係。
iris_dataframe = pd.DataFrame(X_train, columns=iris_dataset.feature_names)   # 我們首先將numpy陣列轉換成pandas的dataform, 

pd.plotting.scatter_matrix(iris_dataframe, c=y_train, figsize=(15, 15),   # 使用dataform建立散點圖矩陣
                           marker='o', hist_kwds={'bins': 20}, s=60,
                           alpha=.8, cmap=mglearn.cm3)

構建模型 – k近鄰演算法:
呼叫fit方法構建模型

k近鄰演算法:這個模型只需要儲存訓練集就可以了,如果要對一個新的資料點做出預測,演算法只需要在這個訓練集中尋找與這個新的資料點距離最近的資料點,然後將找到的這個sample的標籤直接給這個需要預測的資料點就可以了。這個k的含義是,在資料集中找到與這個新資料點最近的任意k個鄰居,然後找到這些鄰居里面數量最多的類別,將這個類別賦予給新的資料點。

from sklearn.neighbors import KNeighborsClassifier  # sklearn中所有的機器學習模型都在各自的類中實現
knn = KNeighborsClassifier(n_neighbors=1)   # 我們將這個類例項化為一個物件,我們才能使用這個模型,這裡設定鄰居的數量為1

knn.fit(X_train, y_train)   # 基於訓練集構建模型,這裡返回的是knn物件本身並做了原處修改,表明knn模型已經建立

對新資料做出預測:
呼叫predict方法做出預測

X_new = np.array([[5, 2.9, 1, 0.2]])  # 將一朵花的資料轉換為二維陣列numpy中的一行,這是因為sklearn只接受二維陣列
print("X_new.shape:", X_new.shape)
>>> X_new.shape: (1, 4)
prediction = knn.predict(X_new)  # 生成一個預測結果list,因為只有一朵花,所以list中只有一個數字
print("Prediction:", prediction)
print("Predicted target name:", iris_dataset['target_names'][prediction])
>>> Prediction: [0]
	   Predicted target name: ['setosa']

現在我們的模型做出了預測為這朵花編號為0,那麼我們是否能相信這個預測的結果呢?

評估模型:
呼叫score方法算出模型的精確度

這裡就要用到之前預留的test data了,因為裡面的資料不被模型知道,並且我們已知資料對應的標籤。所以我們可以通過模型對test data中的資料進行預測,然後對比我們已知的標籤,計算精度accuracy來評估這個模型:

y_pred = knn.predict(X_test)  # 這是第一種方法,根據模型算出測試資料的標籤
print("Test set score: {:.2f}".format(np.mean(y_pred == y_test)))  #將預測出來的標籤跟已知的正確標籤做比較
>>> Test set score: 0.97

print("Test set score: {:.2f}".format(knn.score(X_test, y_test)))  # 第二種方法是直接使用score算出accuracy
>>> Test set score: 0.97