如何使用多項式特徵變換進行機器學習

通常情況下,預測建模任務的輸入特性以非預期的、通常是非線性的方式進行交互。

這些交互作用可以通過學習算法來識別和建模。另一種方法是設計新特徵來公開這些交互,並觀察它們是否提高了模型的性能。此外,像將輸入變量提升到冪這樣的轉換可以幫助更好地揭示輸入變量和目標變量之間的重要關係。

這些特徵稱為交互作用和多項式特徵,允許使用更簡單的建模算法,因為解釋輸入變量及其關係的一些複雜性被推遲到數據準備階段。有時,這些特徵可以提高建模性能,儘管代價是增加了數千甚至數百萬個額外的輸入變量。

在本文中,您將發現如何將多項式特徵變換用於帶有數字輸入變量的特徵工程。

一些機器學習算法更喜歡多項式輸入特徵,或者在多項式輸入特徵上表現更好。如何使用多項式特徵變換來創建用於預測建模的輸入變量的新版本。多項式的階數如何影響通過轉換創建的輸入特徵的數量。

本文分為五個部分:

多項式特徵多項式特徵變換聲納數據集多項式特徵變換示例多項式的影響

多項式特徵

多項式特徵是通過將現有特徵提升為指數而創建的那些特徵。

例如,如果數據集具有一個輸入特徵X,則多項式特徵將是新特徵(列)的添加,其中通過對X中的值進行平方來計算值,例如X ^ 2。可以對數據集中的每個輸入變量重複此過程,以創建每個變量的轉換版本。

這樣,多項式特徵是一種特徵工程,例如,基於現有特徵創建新的輸入特徵。

多項式的“ degree ”用於控制所添加特徵的數量,例如,度3將為每個輸入變量添加兩個新變量。通常使用較小的度數,例如2或3。

一般來說,使用大於3或4的d是不常見的,因為對於大的d值,多項式曲線可能會變得過分柔韌性,並且會呈現一些非常奇怪的形狀。

添加表示特徵之間相互作用的新變量也是很常見的,例如,新列表示一個變量乘以另一個變量。對於每個輸入變量,也可以重複此操作,從而為每對輸入變量創建一個新的“ 交互 ”變量。

輸入變量的平方或立方將更改概率分佈,將小值和大值分隔開,該分隔隨著指數的大小而增加。

這種分離可以幫助某些機器學習算法做出更好的預測,並且對於迴歸預測建模任務以及具有數字輸入變量的任務通常很常見。

通常,線性算法(例如線性迴歸和邏輯迴歸)對多項式輸入變量的使用響應良好。

線性迴歸在模型參數中是線性的,向模型添加多項式項可能是允許模型識別非線性模式的有效方法。

多項式特徵變換

多項式特徵變換可以在scikit-learn Python機器學習庫中通過多項式特徵類獲得

創建的特徵包括:

偏差(1.0的值)

每一度的冪(例如x^1, x^2, x^3,…)

所有特徵對之間的交互(例如x1 * x2, x1 * x3,…)

例如,對於兩個值為2和3、度為2的輸入變量,創建的特徵如下:

1(偏差)

2 ^ 1 = 2

3 ^ 1 = 3

2 ^ 2 = 4

3 ^ 2 = 9

2 * 3 = 6

<code>from numpy import asarray from sklearn.preprocessing import PolynomialFeatures # define the dataset data = asarray([[2,3],[2,3],[2,3]]) print(data) # perform a polynomial features transform of the dataset trans = PolynomialFeatures(degree=2) data = trans.fit_transform(data) print(data)/<code>

運行示例首先報告具有兩個特徵(列)的原始數據,每個特徵具有相同的值(2或3)。

然後創建多項式特徵,得到六個特徵,與上述描述相匹配。

參數“degree”控制創建的特徵的數量,默認值為2。

“interaction_only”參數意味著只包含原始值(度1)和交互(成對的值彼此相乘),默認為False。

“include_bias”參數默認為True,以包含偏差特徵。

我們將進一步研究如何在實際數據集上使用多項式特徵變換。

首先,讓我們介紹一個真實的數據集。

聲納數據集

聲納數據集是一種用於二元分類的標準機器學習數據集。

它包括60個實值輸入和一個兩類目標變量。數據集中有208個例子,這些類是合理平衡的。

基線分類算法使用重複分層10次交叉驗證,分類準確率約為53.4%。使用重複分層10倍交叉驗證,該數據集的最高性能約為88%。

<code>from pandas import read_csv from pandas.plotting import scatter_matrix from matplotlib import pyplot # Load dataset url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv" dataset = read_csv(url, header=None) # summarize the shape of the dataset print(dataset.shape) # summarize each variable print(dataset.describe()) # histograms of the variables dataset.hist() pyplot.show()/<code>

運行這個例子首先總結了加載的數據集的形狀。

這確認了60個輸入變量、一個輸出變量和208行數據。

提供了輸入變量的統計彙總,顯示值是數值,範圍大約在0到1之間。

最後,為每個輸入變量創建一個直方圖。

如果我們忽略這些雜亂的圖,而專注於直方圖本身,我們可以看到許多變量都有一個偏態分佈。

接下來,讓我們在原始數據集上安裝並評估一個機器學習模型。

我們將使用帶有缺省超參數的k-最近鄰算法,並使用重複分層k-fold交叉驗證對其進行評估。

<code>from numpy import mean from numpy import std from pandas import read_csv from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import LabelEncoder from matplotlib import pyplot # load dataset url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv" dataset = read_csv(url, header=None) data = dataset.values # separate into input and output columns X, y = data[:, :-1], data[:, -1] # ensure inputs are floats and output is an integer label X = X.astype('float32') y = LabelEncoder().fit_transform(y.astype('str')) # define and configure the model model = KNeighborsClassifier() # evaluate the model cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) n_scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise') # report model performance print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))/<code>

運行該示例將對原始聲納數據集上的KNN模型進行評估。

我們可以看到,該模型的平均分類準確率約為79.7%,表明它具有一定的技巧(優於53.4%),並處於良好的性能水平(88%)。

接下來,讓我們研究數據集的多項式特徵轉換。

多項式特徵變換的例子

我們可以將多項式特徵變換直接應用於聲納數據集。

在這種情況下,我們將degree調整為3。

<code>from pandas import read_csv from pandas import DataFrame from pandas.plotting import scatter_matrix from sklearn.preprocessing import PolynomialFeatures from matplotlib import pyplot # load dataset url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv" dataset = read_csv(url, header=None) # retrieve just the numeric input values data = dataset.values[:, :-1] # perform a polynomial features transform of the dataset trans = PolynomialFeatures(degree=3) data = trans.fit_transform(data) # convert the array back to a dataframe dataset = DataFrame(data) # summarize print(dataset.shape)/<code>

運行該示例對聲納數據集執行多項式特徵轉換。

我們可以看到,對於原始數據集,我們的特性從61個(60個輸入特徵)增加到了39,711個(39,710個輸入特徵)。

接下來,讓我們評估與前一節相同的KNN模型,

<code>接下來,讓我們評估與前一節相同的KNN模型,from numpy import mean from numpy import std from pandas import read_csv from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import LabelEncoder from sklearn.preprocessing import PolynomialFeatures from sklearn.pipeline import Pipeline from matplotlib import pyplot # load dataset url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv" dataset = read_csv(url, header=None) data = dataset.values # separate into input and output columns X, y = data[:, :-1], data[:, -1] # ensure inputs are floats and output is an integer label X = X.astype('float32') y = LabelEncoder().fit_transform(y.astype('str')) # define the pipeline trans = PolynomialFeatures(degree=3) model = KNeighborsClassifier() pipeline = Pipeline(steps=[('t', trans), ('m', model)]) # evaluate the pipeline cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) n_scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise') # report pipeline performance print('Accuracy: %.3f (%.3f)' % (mean(n_scores), std(n_scores)))/<code>

多項式次數效應

多項式的次數大大增加了輸入特徵的數量。

為了瞭解這對特徵數量的影響程度,我們可以執行不同程度的轉換,並比較數據集中的特徵數量。

<code>from pandas import read_csv from sklearn.preprocessing import LabelEncoder from sklearn.preprocessing import PolynomialFeatures from matplotlib import pyplot # get the dataset def get_dataset(): # load dataset url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv" dataset = read_csv(url, header=None) data = dataset.values # separate into input and output columns X, y = data[:, :-1], data[:, -1] # ensure inputs are floats and output is an integer label X = X.astype('float32') y = LabelEncoder().fit_transform(y.astype('str')) return X, y # define dataset X, y = get_dataset() # calculate change in number of features num_features = list() degress = [i for i in range(1, 6)] for d in degress: # create transform trans = PolynomialFeatures(degree=d) # fit and transform data = trans.fit_transform(X) # record number of features num_features.append(data.shape[1]) # summarize print('Degree: %d, Features: %d' % (d, data.shape[1])) # plot degree vs number of features pyplot.plot(degress, num_features) pyplot.show()/<code>

運行這個示例首先報告1到5的度以及數據集中的特徵數量。

我們可以看到,1度沒有影響,特徵的數量從2急劇增加到5。

這突出表明,對於非常小的數據集以外的任何數據集,都應該使用2或3度來避免輸入變量的急劇增加。

更多的特徵可能導致更多的過度擬合,從而導致更糟糕的結果。

將多項式特徵轉換的次數作為超參數處理並測試數據集的不同值可能是一個好主意。

下面的示例探索了1到4的度值,並使用所選的模型評估它們對分類精度的影響。

<code>from numpy import mean from numpy import std from pandas import read_csv from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import LabelEncoder from sklearn.pipeline import Pipeline from matplotlib import pyplot # get the dataset def get_dataset(): # load dataset url = "https://raw.githubusercontent.com/jbrownlee/Datasets/master/sonar.csv" dataset = read_csv(url, header=None) data = dataset.values # separate into input and output columns X, y = data[:, :-1], data[:, -1] # ensure inputs are floats and output is an integer label X = X.astype('float32') y = LabelEncoder().fit_transform(y.astype('str')) return X, y # get a list of models to evaluate def get_models(): models = dict() for d in range(1,5): # define the pipeline trans = PolynomialFeatures(degree=d) model = KNeighborsClassifier() models[str(d)] = Pipeline(steps=[('t', trans), ('m', model)]) return models # evaluate a give model using cross-validation def evaluate_model(model): cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) scores = cross_val_score(model, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise') return scores # define dataset X, y = get_dataset() # get the models to evaluate models = get_models() # evaluate the models and store results results, names = list(), list() for name, model in models.items(): scores = evaluate_model(model) results.append(scores) names.append(name) print('>%s %.3f (%.3f)' % (name, mean(scores), std(scores))) # plot model performance for comparison pyplot.boxplot(results, labels=names, showmeans=True) pyplot.show()/<code>

運行該示例報告每個多項式度的平均分類精度。

在這種情況下,我們可以看到,除了度3之外,性能通常比沒有轉換(度1)差。

在執行轉換之前或之後對數據進行縮放,以瞭解它如何影響模型性能,這可能會很有趣。

創建盒狀圖和須狀圖來總結每個多項式度的分類精度得分。

我們可以看到,經濟表現保持平穩,可能出現了過度擬合的第一個跡象,即4度。