許多機器學習算法期望數據被一致地縮放。
在為機器學習擴展數據時,你應該考慮兩種常用的方法。
在這個教程中,您將了解如何為機器學習重新縮放您的數據。閱讀完這個教程后,您將知道:
- 如何從頭開始對您的數據進行標準化。
- 如何從頭開始標準化您的數據。
- 何時歸一化數據而不是標準化數據。
描述
許多機器學習算法期望輸入和輸出數據的規模是相當的。
它可以幫助在加權輸入以進行預測的方法中,例如線性回歸和邏輯回歸。
在結合加權輸入以復雜方式的方法中(如人工神經網絡和深度學習)實際上需要這樣做。
在這個教程中,我們將練習對一個標準的機器學習數據集進行重新縮放,該數據集以CSV格式提供。
具體來說,是皮馬印第安人數據集。它包含768行和9列。文件中的所有值都是數值,特別是浮點數。我們將首先學習如何加載文件,然后稍后學習如何將加載的字符串轉換為數值。
- 數據集文件.
- 數據集詳情.
教程
本教程分為3個部分:
- 標準化數據。
- 標準化數據。
- 何時進行歸一化和標準化。
這些步驟將為你處理擴展自己的數據提供必要的基礎。
1. 數據歸一化
正則化可以根據上下文指代不同的技術。
在這里,我們將歸一化定義為將輸入變量重新縮放至0到1的范圍內。
歸一化要求你知道每個屬性的最小值和最大值。
這可以通過訓練數據進行估算,或者如果你對問題領域有深入的了解,可以直接指定。
您可以通過枚舉數據集中的值來輕松估計每個屬性的最小和最大值。
下面的代碼片段定義了dataset_minmax() 函數,該函數計算數據集中每個屬性的最小值和最大值,然后返回這些最小值和最大值的數組。
# Find the min and max values for each column
def dataset_minmax(dataset):minmax = list()for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]value_min = min(col_values)value_max = max(col_values)minmax.append([value_min, value_max])return minmax
我們可以構造一個用于測試的小數據集如下:
x1 x2
50 30
20 90
使用這個人為的數據集,我們可以測試我們的函數,以計算每列的最小值和最大值。
# Find the min and max values for each column
def dataset_minmax(dataset):minmax = list()for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]value_min = min(col_values)value_max = max(col_values)minmax.append([value_min, value_max])return minmax# Contrive small dataset
dataset = [[50, 30], [20, 90]]
print(dataset)
# Calculate min and max for each column
minmax = dataset_minmax(dataset)
print(minmax)
運行示例將產生以下輸出。
首先,數據集以列表的形式打印,然后以格式打印每列的最小值和最大值列1: 最小值,最大值 和 列2: 最小值,最大值。
例如:
[[50, 30], [20, 90]]
[[20, 50], [30, 90]]
一旦我們得到了每列允許的最大值和最小值的估計,我們現在就可以將原始數據歸一化到0到1的范圍內。
將單個值歸一化的計算方法是:
scaled_value = (value - min) / (max - min)
下面是一個在名為normalize_dataset()的函數中的實現,該函數對提供的數據集中的每一列進行值的標準化。
# Rescale dataset columns to the range 0-1
def normalize_dataset(dataset, minmax):for row in dataset:for i in range(len(row)):row[i] = (row[i] - minmax[i][0]) / (minmax[i][1] - minmax[i][0])
我們可以將這個函數與dataset_minmax()函數結合,并對人為數據集進行歸一化。
# Find the min and max values for each column
def dataset_minmax(dataset):minmax = list()for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]value_min = min(col_values)value_max = max(col_values)minmax.append([value_min, value_max])return minmax# Rescale dataset columns to the range 0-1
def normalize_dataset(dataset, minmax):for row in dataset:for i in range(len(row)):row[i] = (row[i] - minmax[i][0]) / (minmax[i][1] - minmax[i][0])# Contrive small dataset
dataset = [[50, 30], [20, 90]]
print(dataset)
# Calculate min and max for each column
minmax = dataset_minmax(dataset)
print(minmax)
# Normalize columns
normalize_dataset(dataset, minmax)
print(dataset)
運行此示例將打印以下輸出,包括標準化的數據集。
[[50, 30], [20, 90]]
[[20, 50], [30, 90]]
[[1, 0], [0, 1]]
我們可以將此代碼與加載CSV數據集的代碼結合起來,加載并標準化皮馬印第安人糖尿病數據集。
下載皮馬印第安人數據集,并將其放置在當前目錄中,文件名pima-indians-diabetes.csv。
- 數據集文件.
打開文件并刪除底部的任何空行。
該示例首先加載數據集,并將每列的值從字符串轉換為浮點數。從數據集中估計每列的最小值和最大值,最后對數據集中的值進行歸一化。
from csv import reader# Load a CSV file
def load_csv(filename):file = open(filename, "rb")lines = reader(file)dataset = list(lines)return dataset# Convert string column to float
def str_column_to_float(dataset, column):for row in dataset:row[column] = float(row[column].strip())# Find the min and max values for each column
def dataset_minmax(dataset):minmax = list()for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]value_min = min(col_values)value_max = max(col_values)minmax.append([value_min, value_max])return minmax# Rescale dataset columns to the range 0-1
def normalize_dataset(dataset, minmax):for row in dataset:for i in range(len(row)):row[i] = (row[i] - minmax[i][0]) / (minmax[i][1] - minmax[i][0])# Load pima-indians-diabetes dataset
filename = 'pima-indians-diabetes.csv'
dataset = load_csv(filename)
print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0]))
# convert string columns to float
for i in range(len(dataset[0])):str_column_to_float(dataset, i)
print(dataset[0])
# Calculate min and max for each column
minmax = dataset_minmax(dataset)
# Normalize columns
normalize_dataset(dataset, minmax)
print(dataset[0])
運行示例會生成以下輸出。
從數據集中打印出第一條評論,在標準化之前和之后,顯示了縮放的效果。
Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns
[6.0, 148.0, 72.0, 35.0, 0.0, 33.6, 0.627, 50.0, 1.0]
[0.35294117647058826, 0.7437185929648241, 0.5901639344262295, 0.35353535353535354, 0.0, 0.5007451564828614, 0.23441502988898377, 0.48333333333333334, 1.0]
2. 標準化數據
標準化是一種重新縮放技術,指的是將數據的分布以0為中心,并將標準差調整到1。
平均值和標準差可以一起用來總結正態分布,也稱為高斯分布或鐘形曲線。
它要求在縮放之前已知每列值的均值和標準差。與上面的歸一化類似,我們可以從訓練數據中估計這些值,或者使用領域知識來指定它們的值。
讓我們從創建函數開始,以從數據集中估計每列的均值和標準差統計數據。
均值描述了一組數字的中間或集中趨勢。列的均值是通過將列的所有值相加并除以總值數量來計算的。
mean = sum(values) / total_values
下面的函數 column_means() 用于計算數據集中每列的平均值。
# calculate column means
def column_means(dataset):means = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]means[i] = sum(col_values) / float(len(dataset))return means
標準差描述了值從平均值的平均偏差。它可以通過將每個值與平均值的差值平方后求和,然后除以值的數量減去1,再開方來計算。
standard deviation = sqrt( (value_i - mean)^2 / (total_values-1))
下面的函數 column_stdevs() 計算數據集中每列的值的標準差,并假定已經計算出均值。
# calculate column standard deviations
def column_stdevs(dataset, means):stdevs = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):variance = [pow(row[i]-means[i], 2) for row in dataset]stdevs[i] = sum(variance)stdevs = [sqrt(x/(float(len(dataset)-1))) for x in stdevs]return stdevs
再次,我們可以構造一個小型數據集來演示從數據集中估計均值和標準差。
x1 x2
50 30
20 90
30 50
使用Excel電子表格,我們可以估算出每列的均值和標準差如下:
x1 x2
mean 33.3 56.6
stdev 15.27 30.55
使用人為構造的數據集,我們可以估計總結統計量。
from math import sqrt# calculate column means
def column_means(dataset):means = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]means[i] = sum(col_values) / float(len(dataset))return means# calculate column standard deviations
def column_stdevs(dataset, means):stdevs = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):variance = [pow(row[i]-means[i], 2) for row in dataset]stdevs[i] = sum(variance)stdevs = [sqrt(x/(float(len(dataset)-1))) for x in stdevs]return stdevs# Standardize dataset
dataset = [[50, 30], [20, 90], [30, 50]]
print(dataset)
# Estimate mean and standard deviation
means = column_means(dataset)
stdevs = column_stdevs(dataset, means)
print(means)
print(stdevs)
執行此示例將產生以下輸出,與電子表格中計算的數字匹配。
[[50, 30], [20, 90], [30, 50]]
[33.333333333333336, 56.666666666666664]
[15.275252316519467, 30.550504633038933]
一旦計算了匯總統計數據,我們就可以輕松地對每列中的值進行標準化。
將給定值標準化的計算方法如下:
standardized_value = (value - mean) / stdev
下面是一個名為standardize_dataset()的函數,實現了這個方程
# standardize dataset
def standardize_dataset(dataset, means, stdevs):for row in dataset:for i in range(len(row)):row[i] = (row[i] - means[i]) / stdevs[i]
將這些函數與用于估計均值和標準差的匯總統計數據結合起來,我們可以對我們的虛構數據集進行標準化。
from math import sqrt# calculate column means
def column_means(dataset):means = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]means[i] = sum(col_values) / float(len(dataset))return means# calculate column standard deviations
def column_stdevs(dataset, means):stdevs = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):variance = [pow(row[i]-means[i], 2) for row in dataset]stdevs[i] = sum(variance)stdevs = [sqrt(x/(float(len(dataset)-1))) for x in stdevs]return stdevs# standardize dataset
def standardize_dataset(dataset, means, stdevs):for row in dataset:for i in range(len(row)):row[i] = (row[i] - means[i]) / stdevs[i]# Standardize dataset
dataset = [[50, 30], [20, 90], [30, 50]]
print(dataset)
# Estimate mean and standard deviation
means = column_means(dataset)
stdevs = column_stdevs(dataset, means)
print(means)
print(stdevs)
# standardize dataset
standardize_dataset(dataset, means, stdevs)
print(dataset)
執行此示例將生成以下輸出,顯示人為數據集的標準化值。
[[50, 30], [20, 90], [30, 50]]
[33.333333333333336, 56.666666666666664]
[15.275252316519467, 30.550504633038933]
[[1.0910894511799618, -0.8728715609439694], [-0.8728715609439697, 1.091089451179962], [-0.21821789023599253, -0.2182178902359923]]
再次強調,我們可以展示機器學習數據集的標準化。
下面的示例展示了如何加載和標準化Pima Indians糖尿病數據集,假設該數據集位于當前工作目錄,如之前的標準化示例所示。
from csv import reader
from math import sqrt# Load a CSV file
def load_csv(filename):file = open(filename, "rb")lines = reader(file)dataset = list(lines)return dataset# Convert string column to float
def str_column_to_float(dataset, column):for row in dataset:row[column] = float(row[column].strip())# calculate column means
def column_means(dataset):means = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):col_values = [row[i] for row in dataset]means[i] = sum(col_values) / float(len(dataset))return means# calculate column standard deviations
def column_stdevs(dataset, means):stdevs = [0 for i in range(len(dataset[0]))]for i in range(len(dataset[0])):variance = [pow(row[i]-means[i], 2) for row in dataset]stdevs[i] = sum(variance)stdevs = [sqrt(x/(float(len(dataset)-1))) for x in stdevs]return stdevs# standardize dataset
def standardize_dataset(dataset, means, stdevs):for row in dataset:for i in range(len(row)):row[i] = (row[i] - means[i]) / stdevs[i]# Load pima-indians-diabetes dataset
filename = 'pima-indians-diabetes.csv'
dataset = load_csv(filename)
print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0]))
# convert string columns to float
for i in range(len(dataset[0])):str_column_to_float(dataset, i)
print(dataset[0])
# Estimate mean and standard deviation
means = column_means(dataset)
stdevs = column_stdevs(dataset, means)
# standardize dataset
standardize_dataset(dataset, means, stdevs)
print(dataset[0])
運行示例會打印數據集的第一行,首先以原始格式加載,然后進行標準化,這樣我們可以進行比較以查看差異。
Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns
[6.0, 148.0, 72.0, 35.0, 0.0, 33.6, 0.627, 50.0, 1.0]
[0.6395304921176576, 0.8477713205896718, 0.14954329852954296, 0.9066790623472505, -0.692439324724129, 0.2038799072674717, 0.468186870229798, 1.4250667195933604, 1.3650063669598067]
3. 歸一化和標準化的時機
標準化是一種假設您的數據符合正態分布的縮放技術。
如果給定的數據屬性是正常或接近正常,這可能是應該使用的縮放方法。
記錄標準化過程中使用的摘要統計數據是良好的實踐,這樣你可以在將來標準化你可能希望用于模型的數據時應用它們。
歸一化是一種不需要假設任何特定分布的縮放技術。
如果您的數據不是正態分布的,請在應用機器學習算法之前考慮將其標準化。
在歸一化過程中,記錄每個列的最小值和最大值是良好的實踐,以便將來在使用您的模型時,可以對新數據進行歸一化。