Machine Learning Mastery 机器学习算法教程(五)

原文:Machine Learning Mastery

协议:CC BY-NC-SA 4.0

如何用 Python 从零开始实现堆叠泛化

原文: machinelearningmastery.com/implementing-stacking-scratch-python/

使用 Python 从零开始编写栈集合,循序渐进。

集合方法是提高机器学习问题预测表现的绝佳方法。

堆叠泛化或堆叠是一种集合技术,它使用新模型来学习如何最佳地组合来自数据集上训练的两个或更多模型的预测。

在本教程中,您将了解如何在 Python 中从零开始实现堆叠。

完成本教程后,您将了解:

  • 如何学习在数据集上组合多个模型的预测。
  • 如何将叠加泛化应用于实际预测性建模问题。

让我们开始吧。

  • 2017 年 1 月更新:将 cross_validation_split()中的 fold_size 计算更改为始终为整数。修复了 Python 3 的问题。
  • 更新 Aug / 2018 :经过测试和更新,可与 Python 3.6 配合使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如何使用 Python 从零开始实现堆叠
Kiran Foster 的照片,保留一些权利。

描述

本节简要概述了本教程中使用的 Stacked Generalization 算法和 Sonar 数据集。

叠加泛化算法

堆叠泛化或堆叠是一种集成算法,其中训练新模型以组合来自已经训练的两个或更多模型或您的数据集的预测。

来自现有模型或子模型的预测使用新模型组合,并且因为这种堆叠通常被称为混合,因为来自子模型的预测被混合在一起。

通常使用简单的线性方法将子模型的预测(例如简单平均或投票)与使用线性回归或逻辑回归的加权和相结合。

将预测结合起来的模型必须掌握问题的技巧,但不需要是最好的模型。这意味着您不需要专心调整子模型,只要模型显示出优于基线预测的优势。

子模型产生不同的预测非常重要,即所谓的不相关预测。当组合的预测都是熟练的,但以不同的方式熟练时,堆叠效果最佳。这可以通过使用使用非常不同的内部表示(与实例相比的树)和/或在训练数据的不同表示或投影上训练的模型的算法来实现。

在本教程中,我们将考虑采用两个非常不同且未调整的子模型,并将它们的预测与简单的逻辑回归算法相结合。

声纳数据集

我们将在本教程中使用的数据集是 Sonar 数据集。

这是一个描述声纳啁啾返回从不同表面反弹的数据集。 60 个输入变量是不同角度的回报强度。这是一个二分类问题,需要一个模型来区分岩石和金属圆柱。共有 208 个观测结果。

这是一个众所周知的数据集。所有变量都是连续的,通常在 0 到 1 的范围内。输出变量是我的字符串“M”和摇滚的“R”,需要将其转换为整数 1 和 0。

通过预测数据集(M 或矿)中具有最多观测值的类,零规则算法可以实现约 53%的准确度。

您可以在 UCI 机器学习库中了解有关此数据集的更多信息。

免费下载数据集并将其放在工作目录中,文件名为 sonar.all-data.csv

教程

本教程分为 3 个步骤:

  1. 子模型和聚合器。
  2. 结合预测。
  3. 声纳数据集案例研究。

这些步骤为您在自己的预测性建模问题上理解和实现堆叠提供了基础。

1.子模型和聚合器

我们将使用两个模型作为子模型进行堆叠,使用线性模型作为聚合器模型。

这部分分为 3 个部分:

  1. 子模型#1:K 最近邻。
  2. 子模型#2:感知机。
  3. 聚合器模型:逻辑回归。

每个模型将根据用于训练模型的函数和用于做出预测的函数来描述。

1.1 子模型#1:k-最近邻居

K 最近邻算法或 kNN 使用整个训练数据集作为模型。

因此,训练模型涉及保留训练数据集。下面是一个名为 **knn_model()**的函数。

# Prepare the kNN model
def knn_model(train):
	return train

做出预测涉及在训练数据集中查找 k 个最相似的记录并选择最常见的类值。欧几里德距离函数用于计算训练数据集中新行数据和行之间的相似性。

以下是涉及对 kNN 模型做出预测的这些辅助函数。函数 **euclidean_distance()**计算两行数据之间的距离, **get_neighbors()**定位训练数据集中所有邻居的新行数据和 knn_predict() 从邻居做出新行数据的预测。

# Calculate the Euclidean distance between two vectors
def euclidean_distance(row1, row2):
	distance = 0.0
	for i in range(len(row1)-1):
		distance += (row1[i] - row2[i])**2
	return sqrt(distance)

# Locate neighbors for a new row
def get_neighbors(train, test_row, num_neighbors):
	distances = list()
	for train_row in train:
		dist = euclidean_distance(test_row, train_row)
		distances.append((train_row, dist))
	distances.sort(key=lambda tup: tup[1])
	neighbors = list()
	for i in range(num_neighbors):
		neighbors.append(distances[i][0])
	return neighbors

# Make a prediction with kNN
def knn_predict(model, test_row, num_neighbors=2):
	neighbors = get_neighbors(model, test_row, num_neighbors)
	output_values = [row[-1] for row in neighbors]
	prediction = max(set(output_values), key=output_values.count)
	return prediction

您可以看到邻居数(k)设置为 2 作为 **knn_predict()**函数的默认参数。这个数字是经过一些试验和错误选择的,没有调整。

现在我们已经有了 kNN 模型的构建块,让我们来看看 Perceptron 算法。

1.2 子模型#2:感知机

Perceptron 算法的模型是从训练数据中学习的一组权重。

为了训练权重,需要对训练数据进行许多预测以便计算误差值。因此,模型训练和预测都需要预测功能。

下面是实现 Perceptron 算法的辅助函数。 **perceptron_model()**函数在训练数据集上训练 Perceptron 模型, **perceptron_predict()**用于对一行数据做出预测。

# Make a prediction with weights
def perceptron_predict(model, row):
	activation = model[0]
	for i in range(len(row)-1):
		activation += model[i + 1] * row[i]
	return 1.0 if activation >= 0.0 else 0.0

# Estimate Perceptron weights using stochastic gradient descent
def perceptron_model(train, l_rate=0.01, n_epoch=5000):
	weights = [0.0 for i in range(len(train[0]))]
	for epoch in range(n_epoch):
		for row in train:
			prediction = perceptron_predict(weights, row)
			error = row[-1] - prediction
			weights[0] = weights[0] + l_rate * error
			for i in range(len(row)-1):
				weights[i + 1] = weights[i + 1] + l_rate * error * row[i]
	return weights

**perceptron_model()**模型将学习率和训练时期数指定为默认参数。同样,这些参数是通过一些试验和错误选择的,但没有在数据集上进行调整。

我们现在已经实现了两个子模型,让我们看一下实现聚合器模型。

1.3 聚合器模型:逻辑回归

与 Perceptron 算法一样,逻辑回归使用一组称为系数的权重作为模型的表示。

与 Perceptron 算法一样,通过迭代地对训练数据做出预测并更新它们来学习系数。

以下是用于实现逻辑回归算法的辅助函数。 **logistic_regression_model()**函数用于训练训练数据集上的系数, **logistic_regression_predict()**用于对一行数据做出预测。

# Make a prediction with coefficients
def logistic_regression_predict(model, row):
	yhat = model[0]
	for i in range(len(row)-1):
		yhat += model[i + 1] * row[i]
	return 1.0 / (1.0 + exp(-yhat))

# Estimate logistic regression coefficients using stochastic gradient descent
def logistic_regression_model(train, l_rate=0.01, n_epoch=5000):
	coef = [0.0 for i in range(len(train[0]))]
	for epoch in range(n_epoch):
		for row in train:
			yhat = logistic_regression_predict(coef, row)
			error = row[-1] - yhat
			coef[0] = coef[0] + l_rate * error * yhat * (1.0 - yhat)
			for i in range(len(row)-1):
				coef[i + 1] = coef[i + 1] + l_rate * error * yhat * (1.0 - yhat) * row[i]
	return coef

**logistic_regression_model()**将学习率和时期数定义为默认参数,并且与其他算法一样,这些参数在一些试验和错误中被发现并且未被优化。

现在我们已经实现了子模型和聚合器模型,让我们看看如何组合多个模型的预测。

2.结合预测

对于机器学习算法,学习如何组合预测与从训练数据集学习非常相似。

可以根据子模型的预测构建新的训练数据集,如下所示:

  • 每行代表训练数据集中的一行。
  • 第一列包含由第一个子模型制作的训练数据集中每一行的预测,例如 K 最近邻。
  • 第二列包含由第二个子模型制作的训练数据集中每一行的预测,例如 Perceptron 算法。
  • 第三列包含训练数据集中行的预期输出值。

下面是构造的堆叠数据集的外观设计示例:

kNN,	Per,	Y
0,	0	0
1,	0	1
0,	1	0
1,	1	1
0,	1	0

然后可以在该新数据集上训练机器学习算法,例如逻辑回归。实质上,这种新的元算法学习如何最好地组合来自多个子模型的预测。

下面是一个名为 **to_stacked_row()**的函数,它实现了为此堆叠数据集创建新行的过程。

该函数将模型列表作为输入,这些用于做出预测。该函数还将函数列表作为输入,一个函数用于对每个模型做出预测。最后,包括训练数据集中的单行。

一行一列构造一个新行。使用每个模型和训练数据行计算预测。然后将训练数据集行的预期输出值添加为行的最后一列。

# Make predictions with sub-models and construct a new stacked row
def to_stacked_row(models, predict_list, row):
	stacked_row = list()
	for i in range(len(models)):
		prediction = predict_listi
		stacked_row.append(prediction)
	stacked_row.append(row[-1])
	return stacked_row

在一些预测性建模问题上,通过在训练行和子模型做出的预测上训练聚合模型,可以获得更大的提升。

这种改进为聚合器模型提供了训练行中所有数据的上下文,以帮助确定如何以及何时最佳地组合子模型的预测。

我们可以通过聚合训练行(减去最后一列)和上面创建的堆叠行来更新我们的 **to_stacked_row()**函数以包含它。

以下是实现此改进的 **to_stacked_row()**函数的更新版本。

# Make predictions with sub-models and construct a new stacked row
def to_stacked_row(models, predict_list, row):
	stacked_row = list()
	for i in range(len(models)):
		prediction = predict_listi
		stacked_row.append(prediction)
	stacked_row.append(row[-1])
	return row[0:len(row)-1] + stacked_row

在您的问题上尝试两种方法以查看哪种方法效果最好是个好主意。

既然我们拥有堆叠泛化的所有部分,我们就可以将它应用于现实世界的问题。

3.声纳数据集案例研究

在本节中,我们将堆叠算法应用于 Sonar 数据集。

该示例假定数据集的 CSV 副本位于当前工作目录中,文件名为 sonar.all-data.csv

首先加载数据集,将字符串值转换为数字,并将输出列从字符串转换为 0 到 1 的整数值。这可以通过辅助函数 load_csv(), **str_column_to_float( )**和 **str_column_to_int()**加载和准备数据集。

我们将使用 k-fold 交叉验证来估计学习模型在看不见的数据上的表现。这意味着我们将构建和评估 k 模型并将表现估计为平均模型误差。分类精度将用于评估模型。这些行为在 cross_validation_split(), **accuracy_metric()**和 **evaluate_algorithm()**辅助函数中提供。

我们将使用上面实现的 K 最近邻,Perceptron 和逻辑回归算法。我们还将使用我们的技术来创建上一步中定义的新堆叠数据集。

开发了新的函数名 stacking()。这个功能做了 4 件事:

  1. 它首先训练一个模型列表(kNN 和 Perceptron)。
  2. 然后,它使用模型做出预测并创建新的堆叠数据集。
  3. 然后,它在堆叠数据集上训练聚合器模型(逻辑回归)。
  4. 然后,它使用子模型和聚合器模型对测试数据集做出预测。

下面列出了完整的示例。

# Test stacking on the sonar dataset
from random import seed
from random import randrange
from csv import reader
from math import sqrt
from math import exp

# Load a CSV file
def load_csv(filename):
	dataset = list()
	with open(filename, 'r') as file:
		csv_reader = reader(file)
		for row in csv_reader:
			if not row:
				continue
			dataset.append(row)
	return dataset

# Convert string column to float
def str_column_to_float(dataset, column):
	for row in dataset:
		row[column] = float(row[column].strip())

# Convert string column to integer
def str_column_to_int(dataset, column):
	class_values = [row[column] for row in dataset]
	unique = set(class_values)
	lookup = dict()
	for i, value in enumerate(unique):
		lookup[value] = i
	for row in dataset:
		row[column] = lookup[row[column]]
	return lookup

# Split a dataset into k folds
def cross_validation_split(dataset, n_folds):
	dataset_split = list()
	dataset_copy = list(dataset)
	fold_size = int(len(dataset) / n_folds)
	for i in range(n_folds):
		fold = list()
		while len(fold) < fold_size:
			index = randrange(len(dataset_copy))
			fold.append(dataset_copy.pop(index))
		dataset_split.append(fold)
	return dataset_split

# Calculate accuracy percentage
def accuracy_metric(actual, predicted):
	correct = 0
	for i in range(len(actual)):
		if actual[i] == predicted[i]:
			correct += 1
	return correct / float(len(actual)) * 100.0

# Evaluate an algorithm using a cross validation split
def evaluate_algorithm(dataset, algorithm, n_folds, *args):
	folds = cross_validation_split(dataset, n_folds)
	scores = list()
	for fold in folds:
		train_set = list(folds)
		train_set.remove(fold)
		train_set = sum(train_set, [])
		test_set = list()
		for row in fold:
			row_copy = list(row)
			test_set.append(row_copy)
			row_copy[-1] = None
		predicted = algorithm(train_set, test_set, *args)
		actual = [row[-1] for row in fold]
		accuracy = accuracy_metric(actual, predicted)
		scores.append(accuracy)
	return scores

# Calculate the Euclidean distance between two vectors
def euclidean_distance(row1, row2):
	distance = 0.0
	for i in range(len(row1)-1):
		distance += (row1[i] - row2[i])**2
	return sqrt(distance)

# Locate neighbors for a new row
def get_neighbors(train, test_row, num_neighbors):
	distances = list()
	for train_row in train:
		dist = euclidean_distance(test_row, train_row)
		distances.append((train_row, dist))
	distances.sort(key=lambda tup: tup[1])
	neighbors = list()
	for i in range(num_neighbors):
		neighbors.append(distances[i][0])
	return neighbors

# Make a prediction with kNN
def knn_predict(model, test_row, num_neighbors=2):
	neighbors = get_neighbors(model, test_row, num_neighbors)
	output_values = [row[-1] for row in neighbors]
	prediction = max(set(output_values), key=output_values.count)
	return prediction

# Prepare the kNN model
def knn_model(train):
	return train

# Make a prediction with weights
def perceptron_predict(model, row):
	activation = model[0]
	for i in range(len(row)-1):
		activation += model[i + 1] * row[i]
	return 1.0 if activation >= 0.0 else 0.0

# Estimate Perceptron weights using stochastic gradient descent
def perceptron_model(train, l_rate=0.01, n_epoch=5000):
	weights = [0.0 for i in range(len(train[0]))]
	for epoch in range(n_epoch):
		for row in train:
			prediction = perceptron_predict(weights, row)
			error = row[-1] - prediction
			weights[0] = weights[0] + l_rate * error
			for i in range(len(row)-1):
				weights[i + 1] = weights[i + 1] + l_rate * error * row[i]
	return weights

# Make a prediction with coefficients
def logistic_regression_predict(model, row):
	yhat = model[0]
	for i in range(len(row)-1):
		yhat += model[i + 1] * row[i]
	return 1.0 / (1.0 + exp(-yhat))

# Estimate logistic regression coefficients using stochastic gradient descent
def logistic_regression_model(train, l_rate=0.01, n_epoch=5000):
	coef = [0.0 for i in range(len(train[0]))]
	for epoch in range(n_epoch):
		for row in train:
			yhat = logistic_regression_predict(coef, row)
			error = row[-1] - yhat
			coef[0] = coef[0] + l_rate * error * yhat * (1.0 - yhat)
			for i in range(len(row)-1):
				coef[i + 1] = coef[i + 1] + l_rate * error * yhat * (1.0 - yhat) * row[i]
	return coef

# Make predictions with sub-models and construct a new stacked row
def to_stacked_row(models, predict_list, row):
	stacked_row = list()
	for i in range(len(models)):
		prediction = predict_listi
		stacked_row.append(prediction)
	stacked_row.append(row[-1])
	return row[0:len(row)-1] + stacked_row

# Stacked Generalization Algorithm
def stacking(train, test):
	model_list = [knn_model, perceptron_model]
	predict_list = [knn_predict, perceptron_predict]
	models = list()
	for i in range(len(model_list)):
		model = model_listi
		models.append(model)
	stacked_dataset = list()
	for row in train:
		stacked_row = to_stacked_row(models, predict_list, row)
		stacked_dataset.append(stacked_row)
	stacked_model = logistic_regression_model(stacked_dataset)
	predictions = list()
	for row in test:
		stacked_row = to_stacked_row(models, predict_list, row)
		stacked_dataset.append(stacked_row)
		prediction = logistic_regression_predict(stacked_model, stacked_row)
		prediction = round(prediction)
		predictions.append(prediction)
	return predictions

# Test stacking on the sonar dataset
seed(1)
# load and prepare data
filename = 'sonar.all-data.csv'
dataset = load_csv(filename)
# convert string attributes to integers
for i in range(len(dataset[0])-1):
	str_column_to_float(dataset, i)
# convert class column to integers
str_column_to_int(dataset, len(dataset[0])-1)
n_folds = 3
scores = evaluate_algorithm(dataset, stacking, n_folds)
print('Scores: %s' % scores)
print('Mean Accuracy: %.3f%%' % (sum(scores)/float(len(scores))))

k 值为 3 用于交叉验证,每次迭代时评估每个折叠 208/3 = 69.3 或略低于 70 的记录。

运行该示例将打印最终配置的分数和分数平均值。

Scores: [78.26086956521739, 76.81159420289855, 69.56521739130434]
Mean Accuracy: 74.879%

扩展

本节列出了您可能有兴趣探索的本教程的扩展。

  • 调谐算法。本教程中用于子模型和聚合模型的算法未经过调整。探索备用配置,看看是否可以进一步提升表现。
  • 预测相关性。如果子模型的预测相关性较弱,则堆叠效果更好。实现计算以估计子模型的预测之间的相关性。
  • 不同的子模型。使用堆叠过程实现更多和不同的子模型。
  • 不同的聚合模型。尝试使用更简单的模型(如平均和投票)和更复杂的聚合模型来查看是否可以提高表现。
  • 更多数据集。将堆叠应用于 UCI 机器学习库中的更多数据集。

你有没有探索过这些扩展?
在下面的评论中分享您的经验。

评论

在本教程中,您了解了如何在 Python 中从零开始实现堆叠算法。

具体来说,你学到了:

  • 如何组合多个模型的预测。
  • 如何将堆叠应用于现实世界的预测性建模问题。

你有什么问题吗?
在下面的评论中提出您的问题,我会尽力回答。

机器学习中的 K 最近邻

原文: machinelearningmastery.com/k-nearest-neighbors-for-machine-learning/

在这篇文章中,您将发现用于分类和回归的 K 最近邻(KNN)算法。阅读这篇文章后你会知道的。

  • KNN 使用的模型表示。
  • 如何使用 KNN 学习模型(暗示,不是)。
  • 如何使用 KNN 做出预测
  • KNN 的许多名称包括不同的字段如何引用它。
  • 如何准备您的数据以充分利用 KNN。
  • 在哪里可以了解有关 KNN 算法的更多信息。

这篇文章是为开发人员编写的,并没有统计或数学方面的背景。重点是算法如何工作以及如何将其用于预测性建模问题。如果您有任何疑问,请发表评论,我会尽力回答。

让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

K 最近邻 for Machine Learning
照片由 Valentin Ottone 保留,保留一些权利。

KNN 模型表示

KNN 的模型表示是整个训练数据集。

它是如此简单。

除了存储整个数据集之外,KNN 没有其他模型,因此无需学习。

有效的实现可以使用诸如 k-d 树之类的复杂数据结构来存储数据,以在预测期间有效地查找和匹配新模式。

由于存储了整个训练数据集,因此您可能需要仔细考虑训练数据的一致性。策划它可能是一个好主意,在新数据可用时经常更新并删除错误和异常数据。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

用 KNN 做出预测

KNN 直接使用训练数据集做出预测。

通过搜索 K 个最相似的实例(邻居)的整个训练集并总结那些 K 个实例的输出变量,对新实例(x)做出预测。对于回归,这可能是平均输出变量,在分类中,这可能是模式(或最常见)类值。

为了确定训练数据集中的哪个 K 实例与新输入最相似,使用距离度量。对于实值输入变量,最常用的距离测量是欧几里德距离

欧几里德距离被计算为跨所有输入属性 j 的新点(x)和现有点(xi)之间的平方差之和的平方根。

EuclideanDistance(x,xi)= sqrt(sum((xj - xij)^ 2))

其他流行的距离措施包括:

  • 汉明距离:计算二进制向量之间的距离(更多)。
  • 曼哈顿距离:使用它们的绝对差值之和计算实际向量之间的距离。也称为城市街区距离(更多)。
  • Minkowski 距离:欧几里德和曼哈顿距离的推广(更多)。

可以使用许多其他距离测量,例如 Tanimoto, JaccardMahalanobis余弦距离。您可以根据数据属性选择最佳距离指标。如果您不确定,可以尝试不同的距离指标和不同的 K 值,并查看哪种混合产生最准确的模型。

如果输入变量在类型上相似(例如,所有测量的宽度和高度),则欧几里德是一种很好的距离测量。如果输入变量在类型上不相似(例如年龄,性别,身高等),曼哈顿距离是一个很好的衡量标准。

可以通过算法调整找到 K 的值。尝试 K 的许多不同值(例如 1 到 21 的值)并查看哪种值最适合您的问题是一个好主意。

KNN 的计算复杂度随着训练数据集的大小而增加。对于非常大的训练集,KNN 可以通过从训练数据集中取样来制作随机,从中计算 K-最相似的实例。

KNN 已经存在了很长时间,并且已经得到很好的研究。因此,不同的学科有不同的名称,例如:

  • 基于实例的学习:原始训练实例用于做出预测。因此,KNN 通常被称为基于实例的学习或基于案例的学习(其中每个训练实例是来自问题域的案例)。
  • 懒惰学习:不需要学习模型,所有工作都在请求预测时进行。因此,KNN 通常被称为懒惰学习算法。
  • 非参数:KNN 对正在解决的问题的功能形式没有做出任何假设。因此,KNN 被称为非参数机器学习算法。

KNN 可用于回归和分类问题。

KNN for Regression

当 KNN 用于回归问题时,预测基于 K-最相似实例的均值或中值。

KNN for Classification

当 KNN 用于分类时,输出可以被计算为具有来自 K-最相似实例的最高频率的类。每个实例本质上都为他们的班级投票,而得票最多的班级则作为预测。

类概率可以被计算为属于新数据实例的 K 个最相似实例的集合中的每个类的样本的归一化频率。例如,在二分类问题(类为 0 或 1)中:

p(class = 0)= count(class = 0)/(count(class = 0)+ count(class = 1))

如果您使用 K 并且您具有偶数个类(例如 2 个),则最好选择具有奇数的 K 值以避免出现平局。反之,当你有一个奇数的类时,使用偶数来表示 K.

通过将 K 扩展 1 并查看训练数据集中下一个最相似实例的类,可以一致地打破关系。

维度的诅咒

KNN 适用于少量输入变量(p),但在输入数量非常大时会遇到困难。

每个输入变量可以被认为是 p 维输入空间的维度。例如,如果您有两个输入变量 x1 和 x2,则输入空间将为 2 维。

随着维数的增加,输入空间的体积以指数速率增加。

在高维度中,可能相似的点可能具有非常大的距离。所有的点都会相互远离,我们对简单的 2 维和 3 维空间距离的直觉就会崩溃。这可能一开始感觉不直观,但这个一般性问题被称为“维度诅咒”。

为 KNN 准备最佳数据

  • 重新缩放数据:如果所有数据具有相同的比例,KNN 的表现要好得多。将数据规范化到[0,1]范围是个好主意。如果数据具有高斯分布,则标准化数据也可能是个好主意。
  • 地址缺失数据:缺少数据意味着无法计算样本之间的距离。可以排除这些样本,也可以估算缺失值。
  • 低维度:KNN 适用于低维数据。您可以在高维数据(数百或数千个输入变量)上尝试它,但要注意它可能不如其他技术那样好。 KNN 可以从减少输入特征空间维度的特征选择中受益。

进一步阅读

如果您有兴趣从零开始在 Python 中实现 KNN,请查看帖子:

以下是从预测性建模角度介绍 KNN 算法的一些优秀的机器学习文本。

  1. 应用预测性建模,第七章用于回归,第十三章用于分类。
  2. 数据挖掘:实用机器学习工具和技术,第 76 和 128 页
  3. 做数据科学:从前线直接谈话,第 71 页
  4. 机器学习,第八章

还可以在维基百科上查看 K 最近邻

摘要

在这篇文章中,您发现了 KNN 机器学习算法。你了解到:

  • KNN 存储它用作其表示的整个训练数据集。
  • KNN 没有学习任何模型。
  • KNN 通过计算输入样本和每个训练实例之间的相似性来及时做出预测。
  • 有许多距离度量可供选择以匹配输入数据的结构。
  • 在使用 KNN 时,重缩放数据是一个好主意,例如使用规范化。

如果您对此帖子或 KNN 算法有任何疑问,请在评论中提出,我会尽力回答。

学习机器学习中的向量量化

原文: machinelearningmastery.com/learning-vector-quantization-for-machine-learning/

K 最近邻的缺点是你需要坚持整个训练数据集。

学习向量量化算法(或简称 LVQ)是一种人工神经网络算法,可让您选择要挂起的训练实例数,并准确了解这些实例的外观。

在这篇文章中,您将发现学习向量量化算法。阅读这篇文章后你会知道:

  • 实际保存到文件的 LVQ 算法使用的表示形式。
  • 可用于使用已学习的 LVQ 模型做出预测的过程。
  • 如何从训练数据中学习 LVQ 模型。
  • 用于从 LVQ 算法获得最佳表现的数据准备。
  • 在哪里可以找到有关 LVQ 的更多信息。

这篇文章是为开发人员编写的,并没有统计或数学方面的背景。该文章重点介绍了算法的工作原理以及如何将其用于预测性建模问题。

如果您对 LVQ 有任何疑问,请发表评论,我会尽力回答。

让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

学习机器学习的向量量化
摄影: Holly Victoria Norval ,保留一些权利。

LVQ 模型表示

LVQ 的表示是码本向量的集合。

LVQ 已经开发出来并且最好被理解为分类算法。它支持二进制(两类)和多分类问题。

码本向量是与训练数据具有相同输入和输出属性的数字列表。例如,如果您的问题是类 0 和 1 的二分类,以及输入宽度,长度高度,那么代码簿向量将包含所有四个属性:宽度,长度,高度和类。

模型表示是从训练数据中学习的固定的码本向量池。它们看起来像训练实例,但每个属性的值都是根据学习过程进行调整的。

在神经网络的语言中,每个码本向量可以被称为神经元,码本向量上的每个属性被称为权重,并且码本向量的集合被称为网络。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

使用 LVQ 模型做出预测

使用 LVQ 码本向量以与 K 最近邻相同的方式做出预测。

通过搜索 K 个最相似的实例的所有码本向量并总结那些 K 个实例的输出变量,对新实例(x)做出预测。对于分类,这是模式(或最常见)类值。

通常,预测是在 K = 1 的情况下进行的,匹配的码本向量称为最佳匹配单元(BMU)。

为了确定训练数据集中的哪个 K 实例与新输入最相似,使用距离度量。对于实值输入变量,最流行的距离测量是欧几里德距离。欧几里德距离被计算为每个属性 j 的新点(x)和现有点(xi)之间的平方差之和的平方根。

EuclideanDistance(x,xi)= sqrt(sum((xj - xij)^ 2))

从数据中学习 LVQ 模型

LVQ 算法从训练数据中学习码本向量。

您必须选择要使用的码本向量数,例如 20 或 40.您可以通过测试训练数据集上的不同配置找到要使用的最佳码本向量数。

学习算法以随机码本向量池开始。这些可以是来自训练数据的随机选择的实例,或者是与训练数据具有相同比例的随机生成的向量。码本向量具有与训练数据相同数量的输入属性。它们还有一个输出类变量。

训练数据集中的实例一次处理一个。对于给定的训练实例,从池中选择最相似的码本向量。

如果码本向量具有与训练实例相同的输出,则码本向量移动到更接近训练实例。如果不匹配,则会进一步移动。向量移动的量由称为 learning_rate 的算法参数控制。

例如,如果类匹配如下,则将码本向量的输入变量(x)移动到更接近训练输入值(t)的学习量中的量:

x = x + learning_rate *(t - x)

将码本变量的输入变量从训练实例移开的相反情况计算如下:

x = x - learning_rate *(t - x)

这将针对每个输入变量重复。

因为选择一个码本向量用于每个训练实例的修改,所以该算法被称为赢者通吃算法或一种竞争学习

对训练数据集中的每个实例重复此过程。训练数据集的一次迭代称为迭代。该过程已完成您必须选择的多个时期(max_epoch),例如 200。

您还必须选择初始学习率(例如 alpha = 0.3)。学习率随着时期而减少,从您在时期 1 指定的大值开始,这对于码本向量进行最大的改变并且在最后一个时期以接近零的小值结束,从而对码本向量进行非常小的改变。

每个时期的学习率计算如下:

learning_rate = alpha *(1 - (epoch / max_epoch))

其中 learning_rate 是当前时期(0 到 max_epoch-1)的学习率,alpha 是在训练开始时为算法指定的学习率,而 max_epoch 是运行算法的时期总数,也是在跑步的开始。

学习过程的直觉是,码本向量池是将训练数据集压缩到最能表征类别分离的点。

LVQ 的数据准备

一般来说,为 LVQ 准备数据是一个好主意,就像为 K 最近邻准备数据一样。

  • 分类:LVQ 是一种分类算法,适用于二进制(两类)和多分类算法。该技术已适用于回归。
  • 多次通过:LVQ 的良好技术涉及在码本向量上执行训练数据集的多次传递(例如,多次学习运行)。第一个具有较高学习率来解决池码本向量,第二个以较小的学习率来微调向量。
  • 多个最佳匹配:LVQ 的扩展选择多个最佳匹配单元以在学习期间进行修改,例如分别针对和远离训练样本绘制的相同类和不同类之一。其他扩展使用每个码本向量的自定义学习率。这些扩展可以改善学习过程。
  • 归一化输入:传统上,输入被归一化(重新缩放)到 0 到 1 之间的值。这是为了避免一个属性支配距离测量。如果输入数据被归一化,则可以选择码本向量的初始值作为 0 和 1 之间的随机值。
  • 特征选择:可以减少输入变量维数的特征选择可以提高方法的准确率。 LVQ 在作为 K 最近邻做出预测时遭受同样的维度诅咒。

进一步阅读

该技术由 Kohonen 开发,他编写了关于 LVQ 的开创性书籍和姐妹方法 Self-Organizing Maps,名为:自组织地图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果您对 LVQ 感兴趣,我强烈推荐这本书。

摘要

在这篇文章中,您发现了 LVQ 算法。你了解到:

  • LVQ 的表示是一小部分码本向量,小于训练数据集。
  • 码本向量用于使用与 K 最近邻相同的技术做出预测。
  • 码本向量是从训练数据集中学习的,当它们匹配良好时将它们移近,当它们是不匹配时将它们移开。
  • 码本向量是训练数据的压缩,以最好地分离类。
  • 传统上,数据准备涉及将输入值标准化为 0 到 1 之间的范围。

您对此帖子或 LVQ 算法有任何疑问吗?发表评论并提出您的问题,我会尽力回答。

机器学习中的线性判别分析

原文: machinelearningmastery.com/linear-discriminant-analysis-for-machine-learning/

逻辑回归是一种传统上仅限于两类分类问题的分类算法。

如果您有两个以上的类,则线性判别分析是首选的线性分类技术。

在这篇文章中,您将发现用于分类预测性建模问题的线性判别分析(LDA)算法。阅读这篇文章后你会知道:

  • 逻辑回归的局限性和线性判别分析的必要性。
  • 从数据中学习的模型表示,可以保存到文件中。
  • 如何根据您的数据估算模型。
  • 如何从学习的 LDA 模型中做出预测。
  • 如何准备数据以充分利用 LDA 模型。

本文面向对应用机器学习感兴趣的开发人员,模型如何工作以及如何使用它们。因此,不需要统计学或线性代数的背景,尽管如果您了解分布的平均值方差,它确实有帮助。

LDA 是制备和应用中的简单模型。关于如何设置模型以及如何推导出预测方程,背后有一些有趣的统计量,但本文未对此进行介绍。

让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习的线性判别分析
照片由 Jamie McCaffrey 拍摄,保留一些权利。

逻辑回归的局限性

逻辑回归是一种简单而强大的线性分类算法。它还有一些限制,表明需要备用线性分类算法。

  • 两类问题。 逻辑回归旨在用于两类或二分类问题。它可以扩展为多分类,但很少用于此目的。
  • 不稳定,分离良好。当类很好地分离时,逻辑回归可能变得不稳定。
  • 不稳定的几个例子。当几乎没有用于估计参数的示例时,逻辑回归可能变得不稳定。

线性判别分析确实解决了这些问题,并且是多分类问题的首选线性方法。即使存在二分类问题,尝试逻辑回归和线性判别分析也是一个好主意。

LDA 模型的表示

LDA 的代表是直截了当的。

它包含数据的统计属性,为每个类计算。对于单个输入变量(x),这是每个类的变量的均值和方差。对于多个变量,这是通过多元高斯计算的相同属性,即均值和协方差矩阵。

这些统计特性根据您的数据估算并插入 LDA 方程式做出预测。这些是您将保存为模型文件的模型值。

我们来看看如何估算这些参数。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

学习 LDA 模型

LDA 对您的数据做了一些简化的假设:

  1. 您的数据是高斯数据,每个变量在绘制时形状像钟形曲线。
  2. 每个属性具有相同的方差,每个变量的值在均值周围平均变化相同的量。

通过这些假设,LDA 模型可以估算每个类别数据的均值和方差。在具有两个类的单变量(单输入变量)情况下,很容易想到这一点。

通过将值的总和除以值的总数,可以以正常方式估计每个类(k)的每个输入(x)的平均值(μ)。

muk = 1 / nk * sum(x)

其中 muk 是类 k 的 x 的平均值,nk 是类 k 的实例数。在所有类别中计算方差,作为每个值与平均值的平均平方差。

sigma ^ 2 = 1 /(n-K)* sum((x-mu)^ 2)

其中 sigma ^ 2 是所有输入(x)的方差,n 是实例的数量,K 是类的数量,mu 是输入 x 的平均值。

用 LDA 做出预测

LDA 通过估计一组新输入属于每个类的概率来做出预测。获得概率最高的类是输出类,并做出预测。

该模型使用贝叶斯定理来估计概率。简言之贝叶斯定理可用于估计输出类别(k)的概率,给定输入(x)使用每个类别的概率和属于每个类别的数据的概率:

P(Y = x | X = x)=(PIk * fk(x))/ sum(PIl * fl(x))

其中 PIk 指的是训练数据中观察到的每个类别(k)的基本概率(例如,对于两类问题中的 50-50 分裂,则为 0.5)。在贝叶斯定理中,这称为先验概率。

PIk = nk / n

上面的 f(x)是属于该类的 x 的估计概率。高斯分布函数用于 f(x)。将高斯插入上述方程并简化我们最终得到下面的等式。这被称为判别函数,并且类被计算为具有最大值将是输出分类(y):

Dk(x)= x *(muk / siga ^ 2) - (muk ^ 2 /(2 * sigma ^ 2))+ ln(PIk)

Dk(x)是给定输入 x 的类 k 的判别函数,muk,sigma ^ 2 和 PIk 都是根据您的数据估计的。

如何为 LDA 准备数据

本节列出了在准备用于 LDA 的数据时可能会考虑的一些建议。

  • 分类问题。这可能不言而喻,但 LDA 旨在用于输出变量是分类的分类问题。 LDA 支持二进制和多分类。
  • 高斯分布。该模型的标准实现假设输入变量的高斯分布。考虑检查每个属性的单变量分布并使用变换使它们看起来更加高斯(例如,指数分布的 log 和 root 以及偏斜分布的 Box-Cox)。
  • 删除异常值。考虑从数据中删除异常值。这些可能会扭曲用于在 LDA 中分离类的基本统计量,例如均值和标准差。
  • 相同的差异。 LDA 假设每个输入变量具有相同的方差。在使用 LDA 之前标准化数据几乎总是一个好主意,因此它的平均值为 0,标准差为 1。

LDA 的扩展

线性判别分析是一种简单有效的分类方法。因为它很简单并且很容易理解,所以该方法有许多扩展和变化。一些流行的扩展包括:

  • 二次判别分析(QDA):每个类使用自己的方差估计(或有多个输入变量时的协方差)。
  • 灵敏判别分析(FDA):使用非线性输入组合,如样条曲线。
  • 正则化判别分析(RDA):将正则化引入方差估计(实际上是协方差),缓和不同变量对 LDA 的影响。

最初的发展被称为线性判别分析或 Fisher 判别分析。多类版本被称为多判别分析。现在,这些都被简称为线性判别分析。

进一步阅读

如果您希望更深入,本节提供了一些额外的资源。我不得不相信这本书统计学习简介:在 R 中的应用程序,本文中的一些描述和符号取自本文,它非常好。

图书

其他

摘要

在这篇文章中,您发现了线性判别分析,用于分类预测性建模问题。你了解到:

  • LDA 的模型表示以及学习模型的实际区别。
  • 如何从训练数据估计 LDA 模型的参数。
  • 如何使用该模型对新数据做出预测。
  • 如何准备数据以充分利用该方法。

你对这篇文章有任何疑问吗?

发表评论并询问,我会尽力回答。

机器学习中的线性回归

原文: machinelearningmastery.com/linear-regression-for-machine-learning/

线性回归可能是统计学和机器学习中最知名且易于理解的算法之一。

在这篇文章中,您将发现线性回归算法,它如何工作以及如何在机器学习项目中最好地使用它。在这篇文章中,您将学习:

  • 为什么线性回归属于统计学和机器学习。
  • 知道线性回归的众多名称。
  • 用于创建线性回归模型的表示和学习算法。
  • 如何使用线性回归进行建模时最好地准备数据。

您不需要知道任何统计量或线性代数来理解线性回归。这是对该技术的温和高级介绍,为您提供足够的背景,以便能够有效地使用它来解决您自己的问题。

让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习的线性回归
照片由 Nicolas Raymond 拍摄,保留一些权利。

统计学不是线性回归吗?

在我们深入了解线性回归的细节之前,您可能会问自己为什么要查看此算法。

这不是一项统计技术吗?

机器学习,更具体地说是预测性建模领域,主要关注的是最小化模型的误差或使可能性最准确的预测,但代价是可解释性。在应用机器学习中,我们将借用,重用和窃取来自许多不同领域的算法,包括统计量并将其用于这些目的。

因此,在统计学领域开发了线性回归,并且作为理解输入和输出数值变量之间关系的模型进行了研究,但是已经被机器学习所借鉴。它既是统计算法又是机器学习算法。

接下来,让我们回顾一下用于指代线性回归模型的一些常用名称。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

许多线性回归的名称

当你开始研究线性回归时,事情会变得非常混乱。

原因是因为线性回归已存在很长时间(超过 200 年)。它已经从每个可能的角度进行了研究,并且通常每个角度都有一个新的和不同的名称。

线性回归是线性模型,例如,假设输入变量(x)和单个输出变量(y)之间存在线性关系的模型。更具体地,y 可以从输入变量(x)的线性组合计算。

当存在单个输入变量(x)时,该方法称为简单线性回归。当存在多个输入变量时,来自统计学的文献通常将该方法称为多元线性回归。

可以使用不同的技术从数据中准备或训练线性回归方程,其中最常见的是普通最小二乘。因此,通常将以这种方式制备的模型称为普通最小二乘线性回归或仅最小二乘回归。

现在我们知道了一些用于描述线性回归的名称,让我们仔细看看所使用的表示。

线性回归模型表示

线性回归是一个有吸引力的模型,因为表示非常简单。

该表示是一个线性方程,它组合了一组特定的输入值(x),该解决方案是该组输入值(y)的预测输出。因此,输入值(x)和输出值都是数字。

线性方程为每个输入值或列分配一个比例因子,称为系数,由大写希腊字母 Beta(B)表示。还增加了一个附加系数,使线具有额外的自由度(例如,在二维图上上下移动),并且通常称为截距或偏置系数。

例如,在一个简单的回归问题(单个 x 和单个 y)中,模型的形式为:

y = B0 + B1 * x

在具有多个输入(x)的较高维度中,该线被称为平面或超平面。因此,该表示是等式的形式和用于系数的特定值(例如,在以上示例中为 B0 和 B1)。

谈论像线性回归这样的回归模型的复杂性是很常见的。这是指模型中使用的系数数量。

当系数变为零时,它有效地消除了输入变量对模型的影响,因此也消除了模型的预测(0 * x = 0)。如果你看一下改变学习算法的正则化方法,通过对系数的绝对大小施加压力,将某些系数调到零来降低回归模型的复杂性,这就变得相关了。

现在我们已经理解了用于线性回归模型的表示,让我们回顾一下我们可以从数据中学习这种表示的一些方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

什么是线性回归?
Estitxu Carton 的照片,保留一些权利。

线性回归学习模型

学习线性回归模型意味着使用我们可用的数据估计表示中使用的系数的值。

在本节中,我们将简要介绍准备线性回归模型的四种技术。这不足以从零开始实现它们,但足以让人了解所涉及的计算和权衡。

还有更多技术,因为模型研究得很好。注意普通的最小二乘法,因为它是一般使用的最常用的方法。还要注意 Gradient Descent,因为它是机器学习课程中最常用的技术。

1.简单线性回归

通过简单的线性回归,当我们有一个输入时,我们可以使用统计来估计系数。

这要求您根据数据计算统计特性,例如均值,标准差,相关性和协方差。所有数据必须可用于遍历和计算统计量。

这在 excel 中很有趣,但在实践中并没有真正有用。

2.普通的最小二乘法

当我们有多个输入时,我们可以使用普通最小二乘来估计系数的值。

普通最小二乘程序试图最小化残差平方和。这意味着给定数据的回归线,我们计算从每个数据点到回归线的距离,将其平方,并将所有平方误差加在一起。这是普通最小二乘法寻求最小化的数量。

该方法将数据视为矩阵,并使用线性代数运算来估计系数的最佳值。这意味着所有数据都必须可用,并且您必须有足够的内存来适应数据并执行矩阵运算。

除非作为线性代数中的练习,否则自己实现普通最小二乘法是不常见的。您更有可能在线性代数库中调用过程。此过程计算速度非常快。

3.梯度下降

当有一个或多个输入时,您可以通过迭代最小化训练数据模型的误差来使用优化系数值的过程。

此操作称为梯度下降,其工作原理是从每个系数的随机值开始。计算每对输入和输出值的平方误差之和。学习率用作比例因子,并且系数在朝向最小化误差的方向上更新。重复该过程直到达到最小和平方误差或者不可能进一步改进。

使用此方法时,必须选择学习率(alpha)参数,该参数确定要在过程的每次迭代中采用的改进步骤的大小。

通常使用线性回归模型来教授梯度下降,因为它相对简单易懂。实际上,当您在行数或可能不适合内存的列数中拥有非常大的数据集时,它非常有用。

4.正规化

线性模型的训练有扩展,称为正则化方法。这些都试图最小化模型在训练数据上的平方误差之和(使用普通最小二乘),但也降低模型的复杂性(如模型中所有系数之和的数量或绝对大小) 。

线性回归正则化程序的两个常见例子是:

  • 套索回归:修改普通最小二乘法以最小化系数的绝对和(称为 L1 正则化)。
  • 岭回归:修改普通最小二乘法以最小化系数的平方绝对和(称为 L2 正则化)。

当输入值存在共线性且普通最小二乘法会过拟合训练数据时,这些方法可以有效使用。

既然您已经了解了一些在线性回归模型中学习系数的技术,那么让我们看一下如何使用模型对新数据做出预测。

用线性回归做出预测

如果表示是一个线性方程,那么做出预测就像解决一组特定输入的方程一样简单。

让我们以一个例子来具体化。想象一下,我们从高度(x)预测重量(y)。我们对这个问题的线性回归模型表示如下:

y = B0 + B1 * x1

要么

重量= B0 + B1 *高度

其中 B0 是偏差系数,B1 是高度列的系数。我们使用学习技术来找到一组好的系数值。一旦找到,我们可以插入不同的高度值来预测重量。

例如,让我们使用 B0 = 0.1 和 B1 = 0.5。让我们将它们插入并计算出身高 182 厘米的人的体重(千克)。

重量= 0.1 + 0.5 * 182

重量= 91.1

您可以看到上面的等式可以绘制为二维线。无论我们有多高,B0 都是我们的起点。我们可以在 100 到 250 厘米的高度上运行并将它们插入等式并获得重量值,从而创建我们的生产线。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

样本高度和权重线性回归

既然我们已经知道如何在学习线性回归模型的情况下做出预测,那么让我们看看准备数据的一些经验法则,以充分利用这种类型的模型。

准备线性回归数据

对线性回归进行了长时间的研究,并且有很多关于如何构建数据以充分利用模型的文献。

因此,在谈论可能令人生畏的这些要求和期望时,有很多复杂性。在实践中,当使用普通最小二乘回归时,您可以更多地使用这些规则,这是最常见的线性回归实现。

使用这些启发式方法尝试不同的数据准备工作,看看哪种方法最适合您的问题。

  • 线性假设。线性回归假设输入和输出之间的关系是线性的。它不支持任何其他内容。这可能是显而易见的,但是当你有很多属性时,记住它是件好事。您可能需要转换数据以使关系成为线性关系(例如,指数关系的对数转换)。
  • 去除噪音。线性回归假设您的输入和输出变量没有噪声。请考虑使用数据清理操作,以便更好地公开和阐明数据中的信号。这对输出变量最重要,如果可能,您希望删除输出变量(y)中的异常值。
  • 删除共线性。当您具有高度相关的输入变量时,线性回归将过拟合您的数据。考虑计算输入数据的成对相关性并删除最相关的数据。
  • 高斯分布。如果输入和输出变量具有高斯分布,则线性回归将进行更可靠的预测。您可以使用变换(例如 log 或 BoxCox)在变量上获得一些好处,使其分布更加高斯。
  • 重新缩放输入:如果使用标准化或标准化重新缩放输入变量,线性回归通常会做出更可靠的预测。

有关模型所做假设的优秀列表,请参阅 Wikipedia 关于线性回归的文章。 普通最小二乘维基百科文章也有很多假设。

进一步阅读

还有更多关于线性回归的内容。在您进行更多阅读之前开始使用它,但是当您想要深入了解时,下面是您可以使用的一些参考。

提及线性回归的机器学习书籍

这些是您可能拥有或可访问的一些机器学习书籍,它们描述了机器学习环境中的线性回归。

线性回归的帖子

以下是我遇到的一些有趣的关于线性回归的文章和博客文章。

对线性回归有更多好的参考,并且倾向于机器学习和预测性建模?发表评论并告诉我。

摘要

在这篇文章中,您发现了用于机器学习的线性回归算法。

你涵盖了很多方面,包括:

  • 描述线性回归模型时使用的通用名称。
  • 模型使用的表示。
  • 学习算法用于估计模型中的系数。
  • 准备用于线性回归的数据时要考虑的经验法则。

尝试线性回归并熟悉它。

您对线性回归或此帖有任何疑问吗?
发表评论并问,我会尽力回答。

机器学习中使用梯度下降的线性回归教程

原文: machinelearningmastery.com/linear-regression-tutorial-using-gradient-descent-for-machine-learning/

随机梯度下降是机器学习中一种重要且广泛使用的算法。

在本文中,您将了解如何使用随机梯度下降来通过最小化训练数据集上的误差来学习简单线性回归模型的系数。

阅读这篇文章后你会知道:

  • 简单线性回归模型的形式。
  • 梯度下降和随机梯度下降之间的差异
  • 如何使用随机梯度下降来学习简单的线性回归模型。

让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用梯度下降进行机器学习的线性回归教程
照片由 Stig Nygaard 拍摄,保留一些权利。

教程数据集

我们正在使用的数据集是完全组成的。

这是原始数据。属性 x 是输入变量,y 是我们试图预测的输出变量。如果我们得到更多数据,我们只有 x 值,我们会对预测 y 值感兴趣。

x	y
1	1
2	3
4	3
3	2
5	5

下面是 x 与 y 的简单散点图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简单线性回归数据集的图

我们可以看到 x 和 y 之间的关系看起来是线性的。在中,我们可能会在从图的左下角对角线到右上角绘制一条线,以概括地描述数据之间的关系。这是一个很好的迹象,表明使用线性回归可能适合这个小数据集。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

简单线性回归

当我们有一个单一的输入属性(x)并且我们想要使用线性回归时,这称为简单线性回归。

通过简单的线性回归,我们希望对数据建模如下:

y = B0 + B1 * x

这是一条线,其中 y 是我们想要预测的输出变量,x 是我们知道的输入变量,B0 和 B1 是我们需要估计的系数。

B0 称为截距,因为它确定了线截取 y 轴的位置。在机器学习中,我们可以称之为偏差,因为它被添加以抵消我们所做的所有预测。 B1 项称为斜率,因为它定义了线的斜率或者在我们添加偏差之前 x 如何转换为 y 值。

该模型称为简单线性回归,因为只有一个输入变量(x)。如果有更多的输入变量(例如 x1,x2 等),那么这将被称为多元回归。

随机梯度下降

梯度下降是通过遵循成本函数的梯度来最小化函数的过程。

这包括了解成本的形式以及衍生物,以便从给定的点知道梯度并且可以在该方向上移动,例如,向下走向最小值。

在机器学习中,我们可以使用一种称为随机梯度下降的类似技术来最小化模型对训练数据的误差。

这种方式的工作方式是每个训练实例一次一个地显示给模型。该模型对训练实例做出预测,计算误差并更新模型以减少下一次预测的误差。

该过程可用于在模型中找到导致训练数据上模型的最小误差的系数集。每次迭代使用以下等式更新机器学习语言中称为权重(w)的系数:

w = w - alpha * delta

其中 w 是要优化的系数或权重,alpha 是您必须配置的学习率(例如 0.1),而梯度是归因于权重的训练数据上的模型的误差。

具有随机梯度下降的简单线性回归

可以使用随机梯度下降找到简单线性回归中使用的系数。

线性回归是线性系统,系数可以使用线性代数进行分析计算。随机梯度下降不用于计算实际中线性回归的系数(在大多数情况下)。

线性回归确实为学习随机梯度下降提供了有用的练习,这是用于通过机器学习算法最小化成本函数的重要算法。

如上所述,我们的线性回归模型定义如下:

y = B0 + B1 * x

Gradient Descent Iteration#1

让我们从两个系数的值 0.0 开始。

B0 = 0.0

B1 = 0.0

y = 0.0 + 0.0 * x

我们可以计算预测误差如下:

错误= p(i) - y(i)

其中 p(i)是我们数据集中第 i 个实例的预测,y(i)是数据集中实例的第 i 个输出变量。

我们现在可以使用第一个训练实例的起点系数来计算 y 的预测值:

x = 1,y = 1

p(i)= 0.0 + 0.0 * 1

p(i)= 0

使用预测输出,我们可以计算出错误:

错误= 0 - 1

错误= -1

我们现在可以在梯度下降的等式中使用此误差来更新权重。我们将首先更新拦截,因为它更容易。

我们可以说 B0 对所有错误负责。这就是说,更新权重将仅使用误差作为梯度。我们可以如下计算 B0 系数的更新:

B0(t + 1)= B0(t) - α*误差

其中 B0(t + 1)是我们将在下一个训练实例上使用的系数的更新版本,B0(t)是 B0 alpha 的当前值是我们的学习率,而误差是我们为训练实例计算的误差。让我们使用 0.01 的小学习率并将值插入等式中,以计算出 B0 的新的和略微优化的值:

B0(t + 1)= 0.0-0.01 * -1.0

B0(t + 1)= 0.01

现在,我们来看看更新 B1 的值。我们使用相同的方程式进行一次小改动。错误由导致它的输入过滤。我们可以使用以下等式更新 B1:

B1(t + 1)= B1(t) - alpha * error * x

在 B1(t + 1)是更新系数的情况下,B1(t)是系数的当前版本,α是与上述相同的学习率,误差是上面计算的相同误差,x 是输入值。

我们可以将我们的数字插入等式并计算 B1 的更新值:

B1(t + 1)= 0.0-0.01 * -1 * 1

B1(t + 1)= 0.01

我们刚刚完成了梯度下降的第一次迭代,我们将权重更新为 B0 = 0.01 和 B1 = 0.01。必须对我们数据集中剩余的 4 个实例重复此过程。

一次通过训练数据集称为时期。

Gradient Descent Iteration#20

让我们一起跳。

你可以再重复这个过程 19 次。这是暴露于模型并更新系数的训练数据的 4 个完整时期。

以下是您应该看到的 20 次迭代中系数的所有值的列表:

B0	B1
0.01	0.01
0.0397	0.0694
0.066527	0.176708
0.08056049	0.21880847
0.1188144616	0.410078328
0.1235255337	0.4147894001
0.1439944904	0.4557273134
0.1543254529	0.4970511637
0.1578706635	0.5076867953
0.1809076171	0.6228715633
0.1828698253	0.6248337715
0.1985444516	0.6561830242
0.2003116861	0.6632519622
0.1984110104	0.657549935
0.2135494035	0.7332419008
0.2140814905	0.7337739877
0.2272651958	0.7601413984
0.2245868879	0.7494281668
0.219858174	0.7352420252
0.230897491	0.7904386102

我认为 20 个迭代或 4 个时期是一个很好的圆数和一个停下来的好地方。如果你愿意,你可以坚持下去。

您的值应该匹配,但由于不同的电子表格程序和不同的精度,可能会有微小的差异。您可以将每对系数插回到简单的线性回归方程中。这很有用,因为我们可以计算每个训练实例的预测,然后计算误差。

下面是学习过程展开时每组系数的误差图。这是一个有用的图表,因为它向我们显示错误随着每次迭代而减少并且开始在结束时反弹一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

线性回归梯度下降误差与迭代

您可以看到我们的最终系数的值为 B0 = 0.230897491 和 B1 = 0.7904386102

让我们将它们插入到我们的简单线性回归模型中,并对训练数据集中的每个点做出预测。

x	y	prediction
1	1	0.9551001992
2	3	1.690342224
4	3	3.160826275
3	2	2.42558425
5	5	3.8960683

我们可以再次绘制我们的数据集,覆盖这些预测(x vs y 和 x vs 预测)。通过 5 个预测绘制一条线让我们了解模型与训练数据的匹配程度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简单线性回归模型

摘要

在这篇文章中,您发现了简单的线性回归模型以及如何使用随机梯度下降来训练它。

您将完成梯度下降的更新规则的应用。您还学习了如何使用学习的线性回归模型做出预测。

您对此帖子或随机梯度下降的简单线性回归有任何疑问吗?发表评论并提出您的问题,我会尽力回答。

如何在 Python 中从零开始加载机器学习数据

原文: machinelearningmastery.com/load-machine-learning-data-scratch-python/

您必须知道如何加载数据,然后才能使用它来训练机器学习模型。

在开始时,最好使用标准文件格式(如逗号分隔值(.csv))来坚持使用小型内存数据集。

在本教程中,您将了解如何从零开始在 Python 中加载数据,包括:

  • 如何加载 CSV 文件。
  • 如何将字符串从文件转换为浮点数。
  • 如何将类值从文件转换为整数。

让我们开始吧。

  • 2016 年 11 月更新:增加了改进的数据加载功能,以跳过空行。
  • 更新 Aug / 2018 :经过测试和更新,可与 Python 3.6 配合使用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如何在 Python 中从零开始加载机器学习数据
照片由 Amanda B ,保留一些权利。

描述

逗号分隔值

小数据集的标准文件格式是逗号分隔值或 CSV。

最简单的形式是,CSV 文件由数据行组成。每行使用逗号(“,”)分成列。

您可以在 RFC 4180:逗号分隔值(CSV)文件的通用格式和 MIME 类型中了解有关 CSV 文件格式的更多信息。

在本教程中,我们将练习以 CSV 格式加载两个不同的标准机器学习数据集。

皮马印第安人糖尿病数据集

第一个是皮马印第安人糖尿病数据集。它包含 768 行和 9 列。

文件中的所有值都是数字,特别是浮点值。我们将首先学习如何加载文件,然后学习如何将加载的字符串转换为数值。

您可以在 UCI 机器学习库上了解有关此数据集的更多信息。

鸢尾花种类数据集

我们将使用的第二个数据集是虹膜花数据集。

它包含 150 行和 4 列。前 3 列是数字。不同之处在于,类值(最终列)是一个字符串,表示一种花。我们将学习如何将数字列从字符串转换为数字以及如何将花种字符串转换为我们可以一致使用的整数。

您可以在 UCI 机器学习库上了解有关此数据集的更多信息。

教程

本教程分为 3 个部分:

  1. 加载文件。
  2. 加载文件并将字符串转换为浮点数。
  3. 加载文件并将字符串转换为整数。

这些步骤将为您处理加载自己的数据提供所需的基础。

1.加载 CSV 文件

第一步是加载 CSV 文件。

我们将使用作为标准库一部分的 csv 模块

csv 模块中的 **reader()**函数将文件作为参数。

我们将创建一个名为 **load_csv()**的函数来包装此行为,该行为将采用文件名并返回我们的数据集。我们将加载的数据集表示为列表列表。第一个列表是观察或行的列表,第二个列表是给定行的列值列表。

以下是加载 CSV 文件的完整功能。

from csv import reader

# Load a CSV file
def load_csv(filename):
	file = open(filename, "r")
	lines = reader(file)
	dataset = list(lines)
	return dataset

我们可以通过加载 Pima Indians 数据集来测试这个函数。下载数据集并将其放在当前工作目录中,名称为 pima-indians-diabetes.csv 。打开文件并删除底部的任何空行。

看一下原始数据文件的前 5 行,我们可以看到以下内容:

6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1

数据是数字的,用逗号分隔,我们可以期望整个文件符合这个期望。

让我们使用新函数并加载数据集。加载后,我们可以报告一些简单的细节,例如加载的行数和列数。

将所有这些放在一起,我们得到以下结果:

from csv import reader

# Load a CSV file
def load_csv(filename):
	file = open(filename, "r")
	lines = reader(file)
	dataset = list(lines)
	return dataset

# Load 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]))

运行此示例我们看到:

Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns

此函数的一个限制是它将从数据文件加载空行并将它们添加到我们的行列表中。我们可以通过向数据集一次添加一行数据并跳过空行来解决这个问题。

下面是 **load_csv()**函数的这个新改进版本的更新示例。

# Example of loading Pima Indians CSV dataset
from csv import reader

# Load a CSV file
def load_csv(filename):
	dataset = list()
	with open(filename, 'r') as file:
		csv_reader = reader(file)
		for row in csv_reader:
			if not row:
				continue
			dataset.append(row)
	return dataset

# Load 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]))

Running this example we see:

Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns

2.将字符串转换为浮点数

大多数(如果不是全部)机器学习算法都喜欢使用数字。

具体而言,优选浮点数。

我们用于加载 CSV 文件的代码将数据集作为列表列表返回,但每个值都是一个字符串。如果我们从数据集中打印出一条记录,我们可以看到这一点:

print(dataset[0])

这会产生如下输出:

['6', '148', '72', '35', '0', '33.6', '0.627', '50', '1']

我们可以编写一个小函数来将我们加载的数据集的特定列转换为浮点值。

下面是这个函数叫做 str_column_to_float()。它会将数据集中的给定列转换为浮点值,小心地在进行转换之前从值中去除任何空格。

def str_column_to_float(dataset, column):
	for row in dataset:
		row[column] = float(row[column].strip())

我们可以通过将它与上面的加载 CSV 函数相结合来测试此函数,并将 Pima Indians 数据集中的所有数值数据转换为浮点值。

完整的例子如下。

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())

# 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]))
print(dataset[0])
# convert string columns to float
for i in range(len(dataset[0])):
	str_column_to_float(dataset, i)
print(dataset[0])

运行此示例,我们看到在转换之前和之后打印的数据集的第一行。我们可以看到每列中的值已从字符串转换为数字。

Loaded data file pima-indians-diabetes.csv with 768 rows and 9 columns
['6', '148', '72', '35', '0', '33.6', '0.627', '50', '1']
[6.0, 148.0, 72.0, 35.0, 0.0, 33.6, 0.627, 50.0, 1.0]

3.将字符串转换为整数

虹膜花数据集与 Pima Indians 数据集类似,因为列包含数字数据。

差异是最后一列,传统上用于保存给定行的预测结果或值。虹膜花数据中的最后一列是鸢尾花种。

下载数据集并将其放在当前工作目录中,文件名为 iris.csv 。打开文件并删除底部的任何空行。

例如,下面是原始数据集的前 5 行。

5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa

一些机器学习算法更喜欢所有值都是数字,包括结果或预测值。

我们可以通过创建地图将虹膜花数据集中的类值转换为整数。

  1. 首先,我们找到所有独特的类值,恰好是:Iris-setosa,Iris-versicolor 和 Iris-virginica。
  2. 接下来,我们为每个分配一个整数值,例如:0,1 和 2。
  3. 最后,我们将所有出现的类字符串值替换为相应的整数值。

下面是一个只调用 **str_column_to_int()**的函数。与之前介绍的 **str_column_to_float()**一样,它在数据集中的单个列上运行。

# Convert string column to integer
def str_column_to_int(dataset, column):
	class_values = [row[column] for row in dataset]
	unique = set(class_values)
	lookup = dict()
	for i, value in enumerate(unique):
		lookup[value] = i
	for row in dataset:
		row[column] = lookup[row[column]]
	return lookup

除了前两个函数之外,我们还可以测试这个新函数,以加载 CSV 文件并将列转换为浮点值。它还将类值的字典映射返回到整数值,以防下游任何用户希望再次将预测转换回字符串值。

下面的示例加载 iris 数据集,然后将前 3 列转换为浮点数,将最后一列转换为整数值。

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())

# Convert string column to integer
def str_column_to_int(dataset, column):
	class_values = [row[column] for row in dataset]
	unique = set(class_values)
	lookup = dict()
	for i, value in enumerate(unique):
		lookup[value] = i
	for row in dataset:
		row[column] = lookup[row[column]]
	return lookup

# Load iris dataset
filename = 'iris.csv'
dataset = load_csv(filename)
print('Loaded data file {0} with {1} rows and {2} columns').format(filename, len(dataset), len(dataset[0]))
print(dataset[0])
# convert string columns to float
for i in range(4):
	str_column_to_float(dataset, i)
# convert class column to int
lookup = str_column_to_int(dataset, 4)
print(dataset[0])
print(lookup)

运行此示例将生成下面的输出。

我们可以在数据类型转换之前和之后看到数据集的第一行。我们还可以看到类值到整数的字典映射。

Loaded data file iris.csv with 150 rows and 5 columns
['5.1', '3.5', '1.4', '0.2', 'Iris-setosa']
[5.1, 3.5, 1.4, 0.2, 1]
{'Iris-virginica': 0, 'Iris-setosa': 1, 'Iris-versicolor': 2}

扩展

您学习了如何加载 CSV 文件和执行基本数据转换。

考虑到从问题到问题可能需要的各种数据清理和转换,数据加载可能是一项困难的任务。

您可以进行许多扩展,以使这些示例对新的和不同的数据文件更加健壮。以下是您可以考虑自己研究和实现的一些想法:

  • 检测并删除文件顶部或底部的空行。
  • 检测并处理列中的缺失值。
  • 检测并处理与文件其余部分的期望不匹配的行。
  • 支持其他分隔符,例如“|”(管道)或空格。
  • 支持更高效的数据结构,如数组。

您可能希望在实践中用于加载 CSV 数据的两个库是 NumPy 和 Pandas。

NumPy 提供 loadtxt()函数,用于将数据文件作为 NumPy 数组加载。 Pandas 提供 read_csv()功能,它在数据类型,文件头等方面提供了很大的灵活性。

评论

在本教程中,您了解了如何在 Python 中从零开始加载机器学习数据。

具体来说,你学到了:

  • 如何将 CSV 文件加载到内存中。
  • 如何将字符串值转换为浮点值。
  • 如何将字符串类值转换为整数编码。

您对加载机器学习数据或此帖子有任何疑问吗?
在评论中提出您的问题,我会尽力回答。

机器学习中的逻辑回归

原文: machinelearningmastery.com/logistic-regression-for-machine-learning/

逻辑回归是统计领域机器学习所借用的另一种技术。

它是二分类问题的首选方法(具有两个类值的问题)。在这篇文章中,您将发现用于机器学习的逻辑回归算法。

阅读这篇文章后你会知道:

  • 描述逻辑回归时使用的许多名称和术语(如 log odds 和 logit)。
  • 用于逻辑回归模型的表示。
  • 用于从数据中学习逻辑回归模型系数的技术。
  • 如何使用学习的逻辑回归模型实际做出预测。
  • 如果你想深入挖掘,可以去哪里获取更多信息。

本文是为对应用机器学习感兴趣的开发人员编写的,特别是预测性建模。您不需要具有线性代数或统计量的背景知识。

让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑回归的学习算法
摄影: Michael Vadon ,保留一些权利。

物流功能

逻辑回归以在该方法的核心使用的函数命名,即逻辑函数。

逻辑函数,也称为 sigmoid 函数,由统计学家开发,用于描述生态中人口增长的特性,迅速上升并最大限度地提高环境的承载能力。它是一条 S 形曲线,可以取任何实数值并将其映射到 0 到 1 之间的值,但绝不会完全达到这些限制。

1 /(1 + e ^ - 值)

其中 e 是自然对数的基数(电子表格中的欧拉数或 EXP()函数),value 是您要转换的实际数值。下面是使用逻辑函数将-5 和 5 之间的数字转换为 0 和 1 范围的图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

物流功能

现在我们知道了逻辑函数是什么,让我们看看它在逻辑回归中是如何使用的。

用于逻辑回归的表示法

逻辑回归使用方程作为表示,非常类似于线性回归。

使用权重或系数值(称为希腊大写字母 Beta)线性组合输入值(x)以预测输出值(y)。与线性回归的主要区别在于,建模的输出值是二进制值(0 或 1)而不是数值。

以下是逻辑回归方程的示例:

y = e ^(b0 + b1 * x)/(1 + e ^(b0 + b1 * x))

其中 y 是预测输出,b0 是偏差或截距项,b1 是单个输入值(x)的系数。输入数据中的每一列都有一个相关的 b 系数(一个恒定的实际值),必须从训练数据中学习。

您将存储在存储器或文件中的模型的实际表示是等式中的系数(β值或 b)。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

逻辑回归预测概率(技术插曲)

逻辑回归模拟默认类(例如第一类)的概率。

例如,如果我们从他们的身高模拟人的性别为男性或女性,那么第一类可能是男性,逻辑回归模型可以写成男性给予一个人身高的概率,或者更正式:

P(性别=男|高)

换句话说,我们正在模拟输入(X)属于默认类(Y = 1)的概率,我们可以正式地将其写为:

P(X)= P(Y = 1 | X)

我们预测概率?我认为逻辑回归是一种分类算法?

注意,必须将概率预测变换为二进制值(0 或 1)以便实际进行概率预测。稍后我们谈论做出预测时会有更多相关内容。

逻辑回归是一种线性方法,但使用逻辑函数转换预测。这样做的影响是我们不能再将预测理解为输入的线性组合,因为我们可以使用线性回归,例如,从上面继续,模型可以表示为:

p(X)= e ^(b0 + b1 * X)/(1 + e ^(b0 + b1 * X))

我不想过多地深入研究数学,但是我们可以如下转换上面的等式(记住我们可以通过向另一方添加自然对数(ln)来从一侧移除 e):

ln(p(X)/ 1-p(X))= b0 + b1 * X.

这很有用,因为我们可以看到右边的输出计算再次是线性的(就像线性回归一样),左边的输入是默认类概率的对数。

左边的这个比率被称为默认等级的几率(它是我们使用赔率的历史,例如,赔率用于赛马而不是概率)。赔率计算为事件概率除以事件概率的比率,例如: 0.8 /(1-0.8),赔率为 4.所以我们可以写:

ln(赔率)= b0 + b1 * X.

因为赔率是对数转换的,所以我们称这个左侧为对数赔率或概率。可以使用其他类型的函数用于变换(其超出范围 _,但是因此通常将关于线性回归方程与概率相关的变换称为链接函数,例如概率链接函数。

我们可以将指数向右移动并将其写为:

赔率= e ^(b0 + b1 * X)

所有这些都有助于我们理解模型确实仍然是输入的线性组合,但这种线性组合与默认类的对数几率相关。

学习逻辑回归模型

必须根据训练数据估算逻辑回归算法的系数(Beta 值 b)。这是使用最大似然估计来完成的。

最大似然估计是各种机器学习算法使用的常用学习算法,尽管它确实对数据的分布做出了假设(当我们谈论准备数据时更多关于此)。

最佳系数将导致模型预测默认类非常接近 1 的值(例如男性)和非常接近 0 的值(例如女性)用于另一类。逻辑回归的最大似然性的直觉是搜索过程寻求系数(Beta 值)的值,其将模型预测的概率中的误差最小化到数据中的概率(例如,如果数据是主要的则概率为 1)类)。

我们不打算进行最大可能性的计算。可以说最小化算法用于优化训练数据系数的最佳值。这通常在实践中使用有效的数值优化算法(如 Quasi-newton 方法)来实现。

当您学习逻辑时,您可以使用更简单的梯度下降算法从零开始实现它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习的逻辑回归
摄影: woodleywonderworks ,保留一些权利。

利用逻辑回归做出预测

使用逻辑回归模型做出预测就像将数字插入逻辑回归方程并计算结果一样简单。

让我们通过一个具体的例子来具体化。

假设我们有一个模型可以根据他们的身高(完全是虚构的)来预测一个人是男性还是女性。鉴于身高 150 厘米的是男性或女性。

我们已经学习了系数 b0 = -100 和 b1 = 0.6。使用上面的等式,我们可以计算出正式为 150 厘米或更高的男性 P(男性身高= 150)的概率。我们将使用 EXP()作为 e,因为如果您在电子表格中键入此示例,则可以使用此功能:

y = e ^(b0 + b1 * X)/(1 + e ^(b0 + b1 * X))

y = exp(-100 + 0.6 * 150)/(1 + EXP(-100 + 0.6 * X))

y = 0.0000453978687

或者该人是男性的概率几乎为零。

在实践中,我们可以直接使用概率。因为这是分类,我们想要一个清晰的答案,我们可以将概率捕捉到二进制类值,例如:

如果 p(男性)<0,则为 0 0.5

如果 p(男性)> = 0.5,则为 1

现在我们已经知道如何使用逻辑回归做出预测,让我们看看如何准备我们的数据以从技术中获得最大收益。

为逻辑回归准备数据

逻辑回归关于数据中的分布和关系的假设与线性回归中的假设大致相同。

许多研究已经用于定义这些假设,并使用精确的概率和统计语言。我的建议是使用这些作为指导或经验法则,并尝试不同的数据准备方案。

最终,在预测性建模机器学习项目中,您将专注于进行准确的预测,而不是解释结果。因此,只要模型健壮且表现良好,您就可以打破一些假设。

  • 二进制输出变量:这可能是显而易见的,因为我们已经提到它,但逻辑回归是针对二进制(两类)分类问题。它将预测属于默认类的实例的概率,可以将其捕捉到 0 或 1 分类中。
  • 去除噪音:逻辑回归假设输出变量(y)没有错误,请考虑从训练数据中删除异常值和可能错误分类的实例。
  • 高斯分布:逻辑回归是一种线性算法(对输出进行非线性变换)。它确实假设输入变量与输出之间存在线性关系。输入变量的数据变换可以更好地暴露这种线性关系,从而可以获得更准确的模型。例如,您可以使用 log,root,Box-Cox 和其他单变量转换来更好地公开此关系。
  • 删除相关输入:与线性回归一样,如果您有多个高度相关的输入,模型可能会过拟合。考虑计算所有输入之间的成对相关性并去除高度相关的输入。
  • 未能收敛:学习系数的预期似然估计过程有可能无法收敛。如果数据中存在许多高度相关的输入或数据非常稀疏(例如输入数据中存在大量零),则会发生这种情况。

进一步阅读

逻辑回归有很多可用的材料。它是生命科学和经济学等五门学科的最爱。

逻辑回归资源

查看下面的一些书籍,了解有关逻辑回归算法的更多详细信息。

机器学习中的逻辑回归

对于机器学习焦点(例如仅在进行准确预测时),请查看下面一些流行机器学习文本中逻辑回归的覆盖范围:

如果我选择一个,我会指向统计学习简介。这是一本很好的书。

摘要

在这篇文章中,您发现了用于机器学习和预测性建模的逻辑回归算法。你涵盖了很多方面并且学到了:

  • 逻辑函数是什么以及如何在逻辑回归中使用它。
  • 逻辑回归中的关键表示是系数,就像线性回归一样。
  • 使用称为最大似然估计的过程估计逻辑回归中的系数。
  • 使用逻辑回归做出预测非常简单,您可以在 Excel 中做出预测。
  • 逻辑回归的数据准备很像线性回归。

您对后退回归或此帖有任何疑问吗?
发表评论并问,我会尽力回答。

机器学习中的逻辑回归教程

原文: machinelearningmastery.com/logistic-regression-tutorial-for-machine-learning/

逻辑回归是用于二分类的最流行的机器学习算法之一。这是因为它是一种简单的算法,可以很好地解决各种各样的问题。

在这篇文章中,您将逐步发现二分类的逻辑回归算法。阅读这篇文章后你会知道:

  • 如何计算物流函数。
  • 如何使用随机梯度下降来学习逻辑回归模型的系数。
  • 如何使用逻辑回归模型做出预测。

这篇文章是为开发人员编写的,不承担统计或概率的背景。打开电子表格并按照说明进行操作。如果您对逻辑回归有任何疑问,请在评论中提出,我会尽力回答。

让我们开始吧。

2016 年 11 月更新:修正了 b0 更新方程中的一个小错字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习的逻辑回归教程
照片由 Brian Gratwicke 拍摄,保留一些权利。

教程数据集

在本教程中,我们将使用一个人为的数据集。

该数据集有两个输入变量(X1 和 X2)和一个输出变量(Y)。输入变量是从高斯分布中提取的实值随机数。输出变量有两个值,使问题成为二分类问题。

原始数据如下所示。

X1		X2		Y
2.7810836	2.550537003	0
1.465489372	2.362125076	0
3.396561688	4.400293529	0
1.38807019	1.850220317	0
3.06407232	3.005305973	0
7.627531214	2.759262235	1
5.332441248	2.088626775	1
6.922596716	1.77106367	1
8.675418651	-0.2420686549	1
7.673756466	3.508563011	1

下面是数据集的图表。您可以看到它完全是人为的,我们可以轻松地绘制一条线来分隔类。

这正是我们要采用逻辑回归模型的方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

逻辑回归教程数据集

物流功能

在我们深入研究逻辑回归之前,让我们来看一下逻辑函数,它是逻辑回归技术的核心。

逻辑函数定义为:

变换= 1 /(1 + e ^ -x)

其中 e 是数值常数 Euler 的数字,x 是输入,我们插入函数。

让我们插入从-5 到+5 的一系列数字,看看逻辑函数如何转换它们:

X	Transformed
-5	0.006692850924
-4	0.01798620996
-3	0.04742587318
-2	0.119202922
-1	0.2689414214
0	0.5
1	0.7310585786
2	0.880797078
3	0.9525741268
4	0.98201379
5	0.9933071491

您可以看到所有输入都已转换为范围[0,1],并且最小的负数导致值接近零,而较大的正数导致值接近 1。您还可以看到 0 转换为 0.5 或新范围的中点。

由此我们可以看出,只要我们的平均值为零,我们就可以将正值和负值插入到函数中,并始终对新范围进行一致的转换。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

物流功能

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

逻辑回归模型

逻辑回归模型采用实值输入并对输入属于默认类(类 0)的概率做出预测。

如果概率> 0.5 我们可以将输出作为默认类(类 0)的预测,否则预测是针对另一个类(类 1)。

对于此数据集,逻辑回归有三个系数,就像线性回归一样,例如:

output = b0 + b1 * x1 + b2 * x2

学习算法的工作是基于训练数据发现系数(b0,b1 和 b2)的最佳值。

与线性回归不同,使用逻辑函数将输出转换为概率:

p(class = 0)= 1 /(1 + e ^( - 输出))

在您的电子表格中,这将写为:

p(class = 0)= 1 /(1 + EXP(-output))

随机梯度下降的逻辑回归

我们可以使用随机梯度下降来估计系数的值。

这是一个简单的过程,可以被机器学习中的许多算法使用。它通过使用模型来计算训练集中每个实例的预测并计算每个预测的误差。

我们可以将随机梯度下降应用于寻找逻辑回归模型系数的问题如下:

给出每个训练实例:

  1. 使用系数的当前值计算预测。
  2. 根据预测误差计算新系数值。

重复该过程,直到模型足够准确(例如,误差下降到某个期望的水平)或者固定次数的迭代。您继续更新训练实例的模型并更正错误,直到模型足够准确或者无法使其更准确。将示出的训练实例的顺序随机化到模型中以混合所做的校正通常是个好主意。

通过更新每种训练模式的模型,我们称之为在线学习。还可以在所有训练实例上收集模型的所有更改,并进行一次大型更新。这种变化称为批量学习,如果您喜欢冒险,可能会对本教程做出很好的扩展。

计算预测

让我们从为每个系数分配 0.0 并计算属于 0 级的第一个训练实例的概率开始。

B0 = 0.0

B1 = 0.0

B2 = 0.0

第一个训练实例是:x1 = 2.7810836,x2 = 2.550537003,Y = 0

使用上面的等式,我们可以插入所有这些数字并计算预测:

预测= 1 /(1 + e ^( - (b0 + b1 * x1 + b2 * x2)))

预测= 1 /(1 + e ^( - (0.0 + 0.0 * 2.7810836 + 0.0 * 2.550537003)))

预测= 0.5

计算新系数

我们可以使用简单的更新方程计算新的系数值。

b = b + alpha (y - 预测)预测(1 - 预测) x

其中 b 是我们正在更新的系数,预测是使用模型做出预测的输出。

Alpha 是您必须在训练开始时指定的参数。这是学习率并控制系数(以及模型)每次更新时的变化或学习量。在线学习中使用较大的学习率(当我们更新每个训练实例的模型时)。良好的值可能在 0.1 到 0.3 的范围内。我们使用 0.3 的值。

您会注意到等式中的最后一项是 x,这是系数的输入值。您会注意到 B0 没有输入。该系数通常称为偏差或截距,我们可以假设它的输入值始终为 1.0。当使用向量或数组实现算法时,此假设可能有所帮助。

让我们使用前一节中的预测(0.5)和系数值(0.0)来更新系数。

b0 = b0 + 0.3 (0-0.5) 0.5 (1-0.5) 1.0

b1 = b1 + 0.3 (0-0.5) 0.5 (1-0.5) 2.7810836

b2 = b2 + 0.3 (0-0.5) 0.5 (1-0.5) 2.550537003

要么

b0 = -0.0375

b1 = -0.104290635

b2 = -0.09564513761

重复这个过程

我们可以重复此过程并更新数据集中每个训练实例的模型。

通过训练数据集的单次迭代称为迭代。对于固定数量的迭代重复随机梯度下降过程是常见的。

在迭代的末尾,您可以计算模型的误差值。因为这是一个分类问题,所以很容易了解模型在每次迭代时的准确度。

下图显示了模型在 10 个时期内的准确度图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

具有梯度下降精度与迭代的逻辑回归

您可以看到模型很快就能在训练数据集上实现 100%的准确率。

在随机梯度下降的 10 个时期之后计算的系数是:

b0 = -0.4066054641

b1 = 0.8525733164

b2 = -1.104746259

作出预测

现在我们已经训练了模型,我们可以用它来做出预测。

我们可以对训练数据集做出预测,但这可以很容易地成为新数据。

使用 10 个时期之后学习的上述系数,我们可以计算每个训练实例的输出值:

0.2987569857
0.145951056
0.08533326531
0.2197373144
0.2470590002
0.9547021348
0.8620341908
0.9717729051
0.9992954521
0.905489323

这些是属于 class = 0 的每个实例的概率。我们可以使用以下方法将它们转换为清晰的类值:

预测= IF(输出&lt; 0.5)然后 0 Else 1

通过这个简单的过程,我们可以将所有输出转换为类值:

0
0
0
0
0
1
1
1
1
1

最后,我们可以在训练数据集上计算模型的准确度:

准确度=(正确的预测/数字预测)* 100

准确度=(10/10)* 100

准确度= 100%

摘要

在这篇文章中,您了解了如何从零开始逐步实现逻辑回归。你了解到:

  • 如何计算物流函数。
  • 如何使用随机梯度下降来学习逻辑回归模型的系数。
  • 如何使用逻辑回归模型做出预测。

您对此帖子或逻辑回归有任何疑问吗?
发表评论并提出问题,我会尽力回答。

机器学习算法迷你课程

原文: machinelearningmastery.com/machine-learning-algorithms-mini-course/

机器学习算法是机器学习的重要组成部分。

您必须了解他们如何努力在该领域取得任何进展。

在这篇文章中,您将发现一个 14 部分的机器学习算法迷你课程,您可以遵循该课程以最终理解机器学习算法。

我们将在本课程中介绍很多内容,您将度过一段美好的时光。让我们开始吧。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

机器学习算法迷你课程
摄影: Jared Tarbell ,保留一些权利。

这门课程是谁?

在我们开始之前,让我们确保您在正确的位置。

  • 本课程适合初学者对机器学习算法的好奇心。
  • 本课程不假设您知道如何编写代码。
  • 本课程不假设数学背景。
  • 本课程不假设机器学习理论的背景。

这个迷你课程将带您参考基础的机器学习算法和 10 种顶级技术。

我们将访问每个算法,让您了解它是如何工作的,但不要过于深入地保持移动。

迷你课程概述

让我们来看看我们将在接下来的 14 节课中介绍的内容。

您可能需要一次又一次地回到此帖子,因此您可能想要将其加入书签。

这个迷你课程分为四个部分:算法基础,线性算法,非线性算法和集成算法。

算法基础

  • 第 1 课:如何在机器学习中谈论数据
  • 第 2 课:支持所有算法的原则
  • 第 3 课:参数和非参数算法
  • 第 4 课:偏见,差异和权衡

线性算法

  • 第 5 课:线性回归
  • 第 6 课:逻辑回归
  • 第 7 课:线性判别分析

非线性算法

  • 第 8 课:分类和回归树
  • 第 9 课:朴素贝叶斯
  • 第 10 课:k-最近邻居
  • 第 11 课:学习向量量化
  • 第 12 课:支持向量机

集成算法

  • 第 13 课:套袋和随机森林
  • 第 14 课:提升和 AdaBoost

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

第 1 课:如何在机器学习中讨论数据

数据在机器学习中起着重要作用。

在谈论数据时,理解并使用正确的术语非常重要。

您如何看待数据?想想电子表格。您有列,行和单元格。

机器学习的统计视角在机器学习算法旨在学习的假设函数(f)的上下文中构建数据。给定一些输入变量(输入),该函数回答关于预测输出变量(输出)的问题。

输出= f(输入)

输入和输出可以称为变量或向量。

计算机科学观点使用一行数据来描述实体(如人)或关于实体的观察。因此,行的列通常称为观察的属性,行本身称为实例。

第 2 课:支持所有算法的原则

有一个共同的原则是所有监督机器学习算法的基础,用于预测性建模。

机器学习算法被描述为学习目标函数(f),其最佳地将输入变量(X)映射到输出变量(Y)。

Y = f(X)

这是一个通用的学习任务,我们希望在未来(Y)中给出预测输入变量(X)的新例子。我们不知道函数(f)的外观或形式。如果我们这样做,我们将直接使用它,我们不需要使用机器学习算法从数据中学习它。

最常见的机器学习类型是学习映射 Y = f(X)来预测新 X 的 Y.这称为预测性建模或预测分析,我们的目标是使最准确的预测成为可能。

第 3 课:参数和非参数算法

什么是参数化机器学习算法?它与非参数机器学习算法有什么不同?

假设可以大大简化学习过程,但也可以限制可以学习的内容。将函数简化为已知形式的算法称为参数机器学习算法。

算法包括两个步骤:

  1. 选择功能的表单。
  2. 从训练数据中学习函数的系数。

参数机器学习算法的一些示例是线性回归和逻辑回归。

不对映射函数的形式做出强有力假设的算法称为非参数机器学习算法。通过不做出假设,他们可以自由地从训练数据中学习任何功能形式。

非参数方法通常更灵活,实现更高的准确率,但需要更多的数据和训练时间。

非参数算法的示例包括支持向量机,神经网络和决策树。

第 4 课:偏见,差异和权衡

通过偏方差权衡的镜头可以最好地理解机器学习算法。

偏差是模型所做的简化假设,使目标函数更容易学习。

通常,参数算法具有较高的偏差,使得它们学习起来快速且易于理解,但通常不太灵活。反过来,它们对复杂问题的预测表现较低,而这些复杂问题无法满足算法偏差的简化假设。

决策树是低偏差算法的示例,而线性回归是高偏差算法的示例。

方差是如果使用不同的训练数据,目标函数的估计将改变的量。目标函数是通过机器学习算法从训练数据估计的,因此我们应该期望算法具有一些方差,而不是零方差。

K 最近邻算法是高方差算法的一个例子,而线性判别分析是低方差算法的一个例子。

任何预测性建模机器学习算法的目标是实现低偏差和低方差。反过来,该算法应该实现良好的预测表现。机器学习算法的参数化通常是平衡偏差和方差的斗争。

  • 增加偏差会减少差异。
  • 增加方差将减少偏差。

第 5 课:线性回归算法

线性回归可能是统计学和机器学习中最知名且易于理解的算法之一。

这不是一项统计技术吗?

预测性建模主要关注最小化模型的误差或使可能性最准确的预测,但代价是可解释性。我们将借用,重用和窃取来自许多不同领域的算法,包括统计量并将其用于这些目的。

线性回归的表示是通过找到称为系数(B)的输入变量的特定权重来描述最符合输入变量(x)和输出变量(y)之间关系的线的等式。

例如:

y = B0 + B1 * x

我们将在给定输入 x 的情况下预测 y,并且线性回归学习算法的目标是找到系数 B0 和 B1 的值。

可以使用不同的技术从数据中学习线性回归模型,例如用于普通最小二乘和梯度下降优化的线性代数解。

线性回归已经存在了 200 多年,并且已经被广泛研究。使用此技术时,一些好的经验法则是删除非常相似(相关)的变量,并尽可能消除数据中的噪音。

这是一种快速而简单的技术和良好的第一种算法。

第 6 课:逻辑回归算法

逻辑回归是统计领域机器学习所借用的另一种技术。它是二分类问题的首选方法(具有两个类值的问题)。

逻辑回归就像线性回归一样,目标是找到加权每个输入变量的系数的值。

与线性回归不同,使用称为逻辑函数的非线性函数来转换输出的预测。

逻辑函数看起来像一个大 S,并将任何值转换为 0 到 1 的范围。这很有用,因为我们可以将一个规则应用于逻辑函数的输出,以将值捕捉到 0 和 1(例如 IF 小于 0.5 然后输出 1)并预测一个类值。

由于学习模型的方式,逻辑回归所做的预测也可以用作属于 0 级或 1 级的给定数据实例的概率。这对于需要给出更多理由的问题非常有用。一个预测。

与线性回归一样,当您删除与输出变量无关的属性以及彼此非常相似(相关)的属性时,逻辑回归确实更有效。

这是一个学习二分类问题的快速模型。

第 7 课:线性判别分析算法

逻辑回归是一种传统上仅限于两类分类问题的分类算法。如果您有两个以上的类,则线性判别分析算法是首选的线性分类技术。

LDA 的代表非常简单。它包含数据的统计属性,为每个类计算。对于单个输入变量,这包括:

  1. 每个班级的平均值。
  2. 在所有类别中计算的方差。

通过计算每个类的判别值并对具有最大值的类做出预测来做出预测。

该技术假设数据具有高斯分布(钟形曲线),因此最好事先从数据中删除异常值。

它是分类预测性建模问题的一种简单而强大的方法。

第 8 课:分类和回归树

决策树是用于预测性建模机器学习的重要算法类型。

决策树模型的表示是二叉树。这是来自算法和数据结构的二叉树,没什么太花哨的。每个节点表示单个输入变量(x)和该变量上的分割点(假设变量是数字)。

树的叶节点包含用于做出预测的输出变量(y)。通过遍历树的分裂直到到达叶节点并在该叶节点处输出类值来做出预测。

树木学习速度快,预测速度非常快。它们通常也可以解决各种问题,并且不需要对数据进行任何特殊准备。

决策树具有很大的方差,并且在集合中使用时可以产生更准确的预测,我们将在第 13 课和第 14 课中讨论这个主题。

第 9 课:朴素贝叶斯算法

Naive Bayes 是一种简单但令人惊讶的强大的预测性建模算法。

该模型由两种类型的概率组成,可以直接从您的训练数据中计算出来:

  1. 每个班级的概率。
  2. 给出每个 x 值的每个类的条件概率。

一旦计算,概率模型可用于使用贝叶斯定理对新数据做出预测。

当您的数据是实值时,通常假设高斯分布(钟形曲线),以便您可以轻松估计这些概率。

朴素贝叶斯被称为朴素,因为它假设每个输入变量是独立的。这是一个强有力的假设,对于实际数据是不现实的,然而,该技术对于大范围的复杂问题非常有效。

第 10 课:K 最近邻算法

KNN 算法非常简单且非常有效。

KNN 的模型表示是整个训练数据集。简单吧?

通过搜索 K 个最相似的实例(邻居)的整个训练集并总结那些 K 个实例的输出变量,对新数据点做出预测。对于回归,这可能是平均输出变量,在分类中,这可能是模式(或最常见)类值。

诀窍在于如何确定数据实例之间的相似性。如果您的属性具有相同的比例(例如,以英寸为单位),则最简单的技术是使用欧几里德距离,您可以根据每个输入变量之间的差异直接计算该数字。

KNN 可能需要大量内存或空间来存储所有数据,但仅在需要预测时才进行计算(或学习),及时。您还可以随着时间的推移更新和策划您的训练实例,以保持预测准确。

距离或接近度的概念可以在非常高的维度(许多输入变量)中分解,这会对算法在您的问题上的表现产生负面影响。这被称为维度的诅咒。它建议您仅使用与预测输出变量最相关的输入变量。

第 11 课:学习向量量化

K 最近邻的缺点是你需要坚持整个训练数据集。

学习向量量化算法(或简称 LVQ)是一种人工神经网络算法,允许您选择要挂起的训练实例数量,并准确了解这些实例应该是什么样子。

LVQ 的表示是码本向量的集合。这些是在开始时随机选择的,并且适于在学习算法的多次迭代中最佳地总结训练数据集。

在学习之后,可以使用码本向量来进行与 K 最近邻类似的预测。通过计算每个码本向量和新数据实例之间的距离来找到最相似的邻居(最佳匹配码本向量)。然后返回最佳匹配单元的类值或(回归情况下的实际值)作为预测。

如果将数据重新缩放到相同范围(例如 0 到 1 之间),则可获得最佳结果。

如果您发现 KNN 在您的数据集上提供了良好的结果,请尝试使用 LVQ 来降低存储整个训练数据集的内存要求。

第 12 课:支持向量机

支持向量机可能是最流行和最受关注的机器学习算法之一。

超平面是分割输入变量空间的线。在 SVM 中,选择超平面以最好地将输入变量空间中的点与其类(0 级或 1 级)分开。

在二维中,您可以将其可视化为一条线,并假设我们的所有输入点都可以被此线完全分开。

SVM 学习算法找到导致超平面最好地分离类的系数。

超平面与最近数据点之间的距离称为边距。可以将两个类分开的最佳或最佳超平面是作为最大边距的线。

只有这些点与定义超平面和分类器的构造有关。

这些点称为支持向量。它们支持或定义超平面。

实际上,优化算法用于找到使裕度最大化的系数的值。

SVM 可能是最强大的开箱即用分类器之一,值得尝试使用您的数据集。

第 13 课:套袋和随机森林

随机森林是最流行和最强大的机器学习算法之一。它是一种称为 Bootstrap Aggregation 或 bagging 的集成机器学习算法。

引导程序是一种用于从数据样本中估计数量的强大统计方法。比如一个意思。您可以获取大量的数据样本,计算平均值,然后平均所有平均值,以便更好地估计真实平均值。

在装袋中,使用相同的方法,但是用于估计整个统计模型,最常见的是决策树。

获取训练数据的多个样本,然后为每个数据样本构建模型。当您需要对新数据做出预测时,每个模型都会做出预测,并对预测进行平均以更好地估计真实输出值。

随机森林是对这种方法的一种调整,其中创建决策树,使得不是选择最佳分裂点,而是通过引入随机性来进行次优分割。

因此,为每个数据样本创建的模型与其他情况相比更加不同,但仍然以其独特和不同的方式准确。结合他们的预测可以更好地估计真实的基础产值。

如果使用具有高方差的算法(如决策树)获得良好的结果,通常可以通过装袋算法获得更好的结果。

第 14 课:提升和 AdaBoost

Boosting 是一种集合技术,试图从许多弱分类器中创建一个强分类器。

这是通过从训练数据构建模型,然后创建第二个模型来尝试从第一个模型中纠正错误来完成的。添加模型直到完美预测训练集或添加最大数量的模型。

AdaBoost 是第一个为二分类开发的真正成功的增强算法。这是理解助力的最佳起点。现代助推方法建立在 AdaBoost 上,最着名的是随机梯度增强机。

AdaBoost 用于短决策树。在创建第一个树之后,每个训练实例上的树的表现用于加权创建的下一个树应该关注每个训练实例的注意力。难以预测的训练数据被赋予更多权重,而易于预测的实例被赋予更少的权重。

模型一个接一个地顺序创建,每个模型更新训练实例上的权重,这些权重影响序列中下一个树所执行的学习。

构建完所有树之后,将对新数据做出预测,并根据训练数据的准确率对每棵树的表现进行加权。

因为通过算法如此关注纠正错误,所以必须删除带有异常值的干净数据。

迷你课程评论

你做到了。做得好!花点时间回顾一下你走了多远:

  • 您发现了如何在机器学习中讨论数据以及所有预测性建模算法的基本原理。
  • 您发现了参数和非参数算法之间的差异以及偏差和方差引入的误差之间的差异。
  • 您发现了三种线性机器学习算法:线性回归,逻辑回归和线性判别分析。
  • 你被介绍了 5 种非线性算法:分类和回归树,朴素贝叶斯,K-最近邻,学习向量量化和支持向量机。
  • 最后,您发现了两种最流行的集成算法:使用决策树进行装袋和使用 AdaBoost 进行提升。

不要轻视这一点,你在很短的时间内走了很长的路。这只是机器学习算法之旅的开始。继续练习和发展你的技能。

你喜欢这个迷你课吗?
您有任何问题或疑点吗?

发表评论并告诉我。

如何在 Python 中从零开始实现朴素贝叶斯

原文: machinelearningmastery.com/naive-bayes-classifier-scratch-python/

朴素贝叶斯算法简单有效,应该是您尝试分类问题的第一种方法之一。

在本教程中,您将学习 Naive Bayes 算法,包括它的工作原理以及如何在 Python 中从零开始实现它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

朴素贝叶斯分类器
摄影: Matt Buck ,保留一些权利

关于朴素贝叶斯

朴素贝叶斯算法是一种直观的方法,它使用属于每个类的每个属性的概率来做出预测。如果您想要概率性地建模预测性建模问题,那么您将提出监督学习方法。

朴素贝叶斯通过假设属于给定类值的每个属性的概率独立于所有其他属性来简化概率的计算。这是一个强有力的假设,但会产生一种快速有效的方法。

给定属性值的类值的概率称为条件概率。通过将条件概率乘以给定类值的每个属性,我们得到属于该类的数据实例的概率。

为了做出预测,我们可以计算属于每个类的实例的概率,并选择具有最高概率的类值。

朴素碱基通常使用分类数据来描述,因为它易于使用比率进行描述和计算。用于我们目的的更有用的算法版本支持数字属性并假设每个数字属性的值是正态分布的(落在钟形曲线上的某处)。同样,这是一个强有力的假设,但仍然提供了可靠的结果。

获取免费算法思维导图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

方便的机器学习算法思维导图的样本。

我已经创建了一个由类型组织的 60 多种算法的方便思维导图。

下载,打印并使用它。

预测糖尿病的发病

我们将在本教程中使用的测试问题是皮马印第安人糖尿病问题

这个问题包括对 Pima 印第安人专利的医疗细节的 768 次观察。记录描述了从患者身上获取的瞬时测量值,例如他们的年龄,怀孕次数和血液检查次数。所有患者均为 21 岁或以上的女性。所有属性都是数字,其单位因属性而异。

每个记录具有类别值,该类别值指示患者在进行测量(1)或不进行测量(0)的 5 年内是否患有糖尿病。

这是一个标准的数据集,已在机器学习文献中进行了大量研究。良好的预测准确率为 70%-76%。

下面是来自 pima-indians.data.csv 文件的示例,以了解我们将要使用的数据(更新:从此处下载)。

Sample from the pima-indians.data.csv file

6,148,72,35,0,33.6,0.627,50,1
1,85,66,29,0,26.6,0.351,31,0
8,183,64,0,0,23.3,0.672,32,1
1,89,66,23,94,28.1,0.167,21,0
0,137,40,35,168,43.1,2.288,33,1

朴素贝叶斯算法教程

本教程分为以下几个步骤:

  1. 句柄数据:从 CSV 文件加载数据并将其拆分为训练和测试数据集。
  2. 汇总数据:总结训练数据集中的属性,以便我们可以计算概率并做出预测。
  3. 做出预测:使用数据集的摘要生成单个预测。
  4. 制作预测:根据测试数据集和汇总的训练数据集生成预测。
  5. 评估准确度:评估为测试数据集做出的预测的准确率,作为所有预测中的正确百分比。
  6. 将它绑在一起:使用所有代码元素来呈现 Naive Bayes 算法的完整且独立的实现。

1.处理数据

我们需要做的第一件事是加载我们的数据文件。数据为 CSV 格式,没有标题行或任何引号。我们可以使用 open 函数打开文件,并使用 csv 模块中的 reader 函数读取数据行。

我们还需要将作为字符串加载的属性转换为可以使用它们的数字。下面是用于加载 Pima indians 数据集的 **loadCsv()**函数。

Load a CSV file of scalars into memory Python

import csv
def loadCsv(filename):
	lines = csv.reader(open(filename, "rb"))
	dataset = list(lines)
	for i in range(len(dataset)):
		dataset[i] = [float(x) for x in dataset[i]]
	return dataset

我们可以通过加载 pima indians 数据集并打印已加载的数据实例的数量来测试此函数。

Test the loadCsv() function Python

filename = 'pima-indians-diabetes.data.csv'
dataset = loadCsv(filename)
print('Loaded data file {0} with {1} rows').format(filename, len(dataset))

运行此测试,您应该看到类似的内容:

Example output of testing the loadCsv() function

Loaded data file pima-indians-diabetes.data.csv rows

接下来,我们需要将数据拆分为 Naive Bayes 可用于做出预测的训练数据集和我们可用于评估模型准确率的测试数据集。我们需要将数据集随机分成训练和数据集,比率为 67%训练和 33%测试(这是在数据集上测试算法的常用比率)。

下面是 **splitDataset()**函数,它将给定数据集拆分为给定的分割比率。

Split a loaded dataset into a train and test datasets Python

import random
def splitDataset(dataset, splitRatio):
	trainSize = int(len(dataset) * splitRatio)
	trainSet = []
	copy = list(dataset)
	while len(trainSet) < trainSize:
		index = random.randrange(len(copy))
		trainSet.append(copy.pop(index))
	return [trainSet, copy]

我们可以通过定义一个包含 5 个实例的模拟数据集来测试它,将其拆分为训练和测试数据集并打印出来以查看哪些数据实例最终到达哪里。

Test the splitDataset() function Python

dataset = [[1], [2], [3], [4], [5]]
splitRatio = 0.67
train, test = splitDataset(dataset, splitRatio)
print('Split {0} rows into train with {1} and test with {2}').format(len(dataset), train, test)

Running this test, you should see something like:

Example output from testing the splitDataset() function

Split 5 rows into train with [[4], [3], [5]] and test with [[1], [2]]

2.总结数据

朴素贝叶斯模型由训练数据集中的数据摘要组成。然后在做出预测时使用此摘要。

收集的训练数据摘要涉及每个属性的平均值和标准偏差,按类别值。例如,如果有两个类值和 7 个数值属性,那么我们需要每个属性(7)和类值(2)组合的均值和标准差,即 14 个属性摘要。

在做出预测以计算属于每个类值的特定属性值的概率时,这些是必需的。

我们可以将此摘要数据的准备工作分解为以下子任务:

  1. 按类别分开数据
  2. 计算平均值
  3. 计算标准差
  4. 总结数据集
  5. 按类别汇总属性
按类别分开数据

第一个任务是按类值分隔训练数据集实例,以便我们可以计算每个类的统计量。我们可以通过创建每个类值的映射到属于该类的实例列表并将实例的整个数据集排序到适当的列表中来实现。

下面的 **separateByClass()**函数就是这样做的。

The separateByClass() function

def separateByClass(dataset):
	separated = {}
	for i in range(len(dataset)):
		vector = dataset[i]
		if (vector[-1] not in separated):
			separated[vector[-1]] = []
		separated[vector[-1]].append(vector)
	return separated

您可以看到该函数假定最后一个属性(-1)是类值。该函数将类值映射返回到数据实例列表。

我们可以使用一些示例数据测试此函数,如下所示:

Testing the separateByClass() function

dataset = [[1,20,1], [2,21,0], [3,22,1]]
separated = separateByClass(dataset)
print('Separated instances: {0}').format(separated)

Running this test, you should see something like:

Output when testing the separateByClass() function

Separated instances: {0: [[2, 21, 0]], 1: [[1, 20, 1], [3, 22, 1]]}
计算平均值

我们需要计算类值的每个属性的平均值。均值是数据的中心中心或中心趋势,我们将在计算概率时将其用作高斯分布的中间。

我们还需要计算类值的每个属性的标准偏差。标准偏差描述了数据传播的变化,我们将用它来表征计算概率时高斯分布中每个属性的预期传播。

标准偏差计算为方差的平方根。方差计算为每个属性值与平均值的平方差的平均值。注意我们使用的是 N-1 方法,它在计算方差时从属性值的数量中减去 1。

Functions to calculate the mean and standard deviations of attributes

import math
def mean(numbers):
	return sum(numbers)/float(len(numbers))

def stdev(numbers):
	avg = mean(numbers)
	variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
	return math.sqrt(variance)

我们可以通过取 1 到 5 的数字的平均值来测试这个。

Code to test the mean() and stdev() functions

numbers = [1,2,3,4,5]
print('Summary of {0}: mean={1}, stdev={2}').format(numbers, mean(numbers), stdev(numbers))

Running this test, you should see something like:

Output of testing the mean() and stdev() functions

Summary of [1, 2, 3, 4, 5]: mean=3.0, stdev=1.58113883008
总结数据集

现在我们有了汇总数据集的工具。对于给定的实例列表(对于类值),我们可以计算每个属性的均值和标准差。

zip 函数将数据实例中每个属性的值分组到它们自己的列表中,以便我们可以计算属性的均值和标准差值。

The summarize() function

def summarize(dataset):
	summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
	del summaries[-1]
	return summaries

我们可以用一些测试数据来测试这个 **summarize()**函数,该数据显示第一和第二数据属性的平均值和标准偏差值明显不同。

Code to test the summarize() function

dataset = [[1,20,0], [2,21,1], [3,22,0]]
summary = summarize(dataset)
print('Attribute summaries: {0}').format(summary)

Running this test, you should see something like:

Output of testing the summarize() function

Attribute summaries: [(2.0, 1.0), (21.0, 1.0)]
按类别汇总属性

我们可以通过首先将训练数据集分成按类分组的实例来将它们整合在一起。然后计算每个属性的摘要。

The summarizeByClass() function

def summarizeByClass(dataset):
	separated = separateByClass(dataset)
	summaries = {}
	for classValue, instances in separated.iteritems():
		summaries[classValue] = summarize(instances)
	return summaries

我们可以用一个小的测试数据集测试这个 **summarizeByClass()**函数。

Code to test the summarizeByClass() function

dataset = [[1,20,1], [2,21,0], [3,22,1], [4,22,0]]
summary = summarizeByClass(dataset)
print('Summary by class value: {0}').format(summary)

Running this test, you should see something like:

Output from testing the summarizeByClass() function

Summary by class value: 
{0: [(3.0, 1.4142135623730951), (21.5, 0.7071067811865476)], 
1: [(2.0, 1.4142135623730951), (21.0, 1.4142135623730951)]}

3.做出预测

我们现在准备使用从我们的训练数据准备的摘要做出预测。做出预测涉及计算给定数据实例属于每个类的概率,然后选择具有最大概率的类作为预测。

我们可以将这部分分为以下任务:

  1. 计算高斯概率密度函数
  2. 计算类概率
  3. 做一个预测
  4. 估计准确度
计算高斯概率密度函数

在给定从训练数据估计的属性的已知平均值和标准偏差的情况下,我们可以使用高斯函数来估计给定属性值的概率。

假定为每个属性和类值准备的属性汇总,结果是给定类值的给定属性值的条件概率。

有关高斯概率密度函数的详细信息,请参阅参考资料。总之,我们将已知细节插入高斯(属性值,平均值和标准偏差)并读取属性值属于类的可能性。

在 **calculateProbability()**函数中,我们首先计算指数,然后计算主要除法。这让我们可以在两条线上很好地拟合方程。

The calculateProbability() function

import math
def calculateProbability(x, mean, stdev):
	exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
	return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent

我们可以使用一些示例数据对此进行测试,如下所示。

Code to test the calculateProbability() function

x = 71.5
mean = 73
stdev = 6.2
probability = calculateProbability(x, mean, stdev)
print('Probability of belonging to this class: {0}').format(probability)

Running this test, you should see something like:

Output from testing the calculateProbability() function

Probability of belonging to this class: 0.0624896575937
计算类概率

现在我们可以计算出属于某个类的属性的概率,我们可以组合数据实例的所有属性值的概率,并得出整个数据实例属于该类的概率。

我们将概率乘以它们,将概率结合在一起。在下面的 **calculateClassProbabilities()**中,通过将每个类的属性概率相乘来计算给定数据实例的概率。结果是类值与概率的映射。

Code for the calculateClassProbabilities() function

def calculateClassProbabilities(summaries, inputVector):
	probabilities = {}
	for classValue, classSummaries in summaries.iteritems():
		probabilities[classValue] = 1
		for i in range(len(classSummaries)):
			mean, stdev = classSummaries[i]
			x = inputVector[i]
			probabilities[classValue] *= calculateProbability(x, mean, stdev)
	return probabilities

我们可以测试 **calculateClassProbabilities()**函数。

Code to test the calculateClassProbabilities() function

summaries = {0:[(1, 0.5)], 1:[(20, 5.0)]}
inputVector = [1.1, '?']
probabilities = calculateClassProbabilities(summaries, inputVector)
print('Probabilities for each class: {0}').format(probabilities)

Running this test, you should see something like:

Output from testing the calculateClassProbabilities() function

Probabilities for each class: {0: 0.7820853879509118, 1: 6.298736258150442e-05}
做一个预测

现在,可以计算属于每个类值的数据实例的概率,我们可以查找最大概率并返回关联类。

**predict()**函数属于那个。

Implementation of the predict() function

def predict(summaries, inputVector):
	probabilities = calculateClassProbabilities(summaries, inputVector)
	bestLabel, bestProb = None, -1
	for classValue, probability in probabilities.iteritems():
		if bestLabel is None or probability > bestProb:
			bestProb = probability
			bestLabel = classValue
	return bestLabel

我们可以测试 **predict()**函数如下:

Code to test the predict() function

summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}
inputVector = [1.1, '?']
result = predict(summaries, inputVector)
print('Prediction: {0}').format(result)

Running this test, you should see something like:

Output of testing the predict() function

Prediction: A

4.做出预测

最后,我们可以通过对测试数据集中的每个数据实例做出预测来估计模型的准确率。 **getPredictions()**将执行此操作并返回每个测试实例的预测列表。

Code for the getPredictions() function

def getPredictions(summaries, testSet):
	predictions = []
	for i in range(len(testSet)):
		result = predict(summaries, testSet[i])
		predictions.append(result)
	return predictions

我们可以测试 **getPredictions()**函数。

Code to test the getPredictions() function

summaries = {'A':[(1, 0.5)], 'B':[(20, 5.0)]}
testSet = [[1.1, '?'], [19.1, '?']]
predictions = getPredictions(summaries, testSet)
print('Predictions: {0}').format(predictions)

Running this test, you should see something like:

Output from testing the getPredictions() function

Predictions: ['A', 'B']

5.获得准确率

可以将预测与测试数据集中的类值进行比较,并且可以将分类精度计算为 0 和 0 之间的准确度比率。和 100%。 **getAccuracy()**将计算此准确率。

Code for the getAccuracy() function

def getAccuracy(testSet, predictions):
	correct = 0
	for x in range(len(testSet)):
		if testSet[x][-1] == predictions[x]:
			correct += 1
	return (correct/float(len(testSet))) * 100.0

我们可以使用下面的示例代码测试 **getAccuracy()**函数。

Code to test the getAccuracy() function

testSet = [[1,1,1,'a'], [2,2,2,'a'], [3,3,3,'b']]
predictions = ['a', 'a', 'a']
accuracy = getAccuracy(testSet, predictions)
print('Accuracy: {0}').format(accuracy)

Running this test, you should see something like:

Output from testing the getAccuracy() function

Accuracy: 66.6666666667

6.把它绑在一起

最后,我们需要将它们结合在一起。

下面提供了从零开始在 Python 中实现的 Naive Bayes 的完整代码清单。

Complete code for implementing Naive Bayes from scratch in Python Python

# Example of Naive Bayes implemented from Scratch in Python
import csv
import random
import math

def loadCsv(filename):
	lines = csv.reader(open(filename, "rb"))
	dataset = list(lines)
	for i in range(len(dataset)):
		dataset[i] = [float(x) for x in dataset[i]]
	return dataset

def splitDataset(dataset, splitRatio):
	trainSize = int(len(dataset) * splitRatio)
	trainSet = []
	copy = list(dataset)
	while len(trainSet) < trainSize:
		index = random.randrange(len(copy))
		trainSet.append(copy.pop(index))
	return [trainSet, copy]

def separateByClass(dataset):
	separated = {}
	for i in range(len(dataset)):
		vector = dataset[i]
		if (vector[-1] not in separated):
			separated[vector[-1]] = []
		separated[vector[-1]].append(vector)
	return separated

def mean(numbers):
	return sum(numbers)/float(len(numbers))

def stdev(numbers):
	avg = mean(numbers)
	variance = sum([pow(x-avg,2) for x in numbers])/float(len(numbers)-1)
	return math.sqrt(variance)

def summarize(dataset):
	summaries = [(mean(attribute), stdev(attribute)) for attribute in zip(*dataset)]
	del summaries[-1]
	return summaries

def summarizeByClass(dataset):
	separated = separateByClass(dataset)
	summaries = {}
	for classValue, instances in separated.iteritems():
		summaries[classValue] = summarize(instances)
	return summaries

def calculateProbability(x, mean, stdev):
	exponent = math.exp(-(math.pow(x-mean,2)/(2*math.pow(stdev,2))))
	return (1 / (math.sqrt(2*math.pi) * stdev)) * exponent

def calculateClassProbabilities(summaries, inputVector):
	probabilities = {}
	for classValue, classSummaries in summaries.iteritems():
		probabilities[classValue] = 1
		for i in range(len(classSummaries)):
			mean, stdev = classSummaries[i]
			x = inputVector[i]
			probabilities[classValue] *= calculateProbability(x, mean, stdev)
	return probabilities

def predict(summaries, inputVector):
	probabilities = calculateClassProbabilities(summaries, inputVector)
	bestLabel, bestProb = None, -1
	for classValue, probability in probabilities.iteritems():
		if bestLabel is None or probability > bestProb:
			bestProb = probability
			bestLabel = classValue
	return bestLabel

def getPredictions(summaries, testSet):
	predictions = []
	for i in range(len(testSet)):
		result = predict(summaries, testSet[i])
		predictions.append(result)
	return predictions

def getAccuracy(testSet, predictions):
	correct = 0
	for i in range(len(testSet)):
		if testSet[i][-1] == predictions[i]:
			correct += 1
	return (correct/float(len(testSet))) * 100.0

def main():
	filename = 'pima-indians-diabetes.data.csv'
	splitRatio = 0.67
	dataset = loadCsv(filename)
	trainingSet, testSet = splitDataset(dataset, splitRatio)
	print('Split {0} rows into train={1} and test={2} rows').format(len(dataset), len(trainingSet), len(testSet))
	# prepare model
	summaries = summarizeByClass(trainingSet)
	# test model
	predictions = getPredictions(summaries, testSet)
	accuracy = getAccuracy(testSet, predictions)
	print('Accuracy: {0}%').format(accuracy)

main()

运行该示例提供如下输出:

Output from running the final code

Split 768 rows into train=514 and test=254 rows
Accuracy: 76.3779527559%

实现扩展

本节为您提供了可以应用的扩展的概念,并使用您在本教程中实现的 Python 代码进行调查。

您已经从零开始在 python 中实现了自己的 Gaussian Naive Bayes 版本。

您可以进一步扩展实现。

  • 计算类概率:更新示例以概括属于每个类的数据实例的概率作为比率。这可以被计算为属于一个类的数据实例的概率除以属于每个类的数据实例的概率之和。例如,A 类的概率为 0.02,B 类的概率为 0.001,属于 A 类的实例的可能性为(0.02 /(0.02 + 0.001))* 100,约为 95.23%。
  • 对数概率:给定属性值的每个类的条件概率很小。当它们相乘时会产生非常小的值,这可能导致浮点下溢(数字太小而无法在 Python 中表示)。对此的常见修复是将概率的对数组合在一起。研究并实现这一改进。
  • 标称属性:更新实现以支持名义属性。这非常相似,您可以为每个属性收集的摘要信息是每个类的类别值的比率。深入了解参考资料以获取更多信息。
  • 不同的密度函数bernoulli或 _ 多项式 _):我们已经看过高斯朴素贝叶斯,但你也可以看看其他分布。实现不同的分布,例如多项式,bernoulli 或内核朴素贝叶斯,它们对属性值的分布和/或它们与类值的关系做出不同的假设。

资源和进一步阅读

本节将提供一些资源,您可以使用这些资源来了解 Naive Bayes 算法的更多信息,包括它的工作原理和原理以及在代码中实现它的实际问题。

问题

有关预测糖尿病发病问题的更多资源。

本节链接到流行的机器学习库中朴素贝叶斯的开源实现。如果您正在考虑实现自己的方法版本以供操作使用,请查看这些内容。

图书

您可能有一本或多本关于应用机器学习的书籍。本节重点介绍有关机器学习的常见应用书籍中涉及朴素贝叶斯的部分或章节。

下一步

采取行动。

按照教程从零开始实现 Naive Bayes。使示例适应另一个问题。遵循扩展并改进实现。

发表评论并分享您的经验。

更新:查看关于使用朴素贝叶斯算法的提示的后续内容:“ Better Naive Bayes:从 Naive Bayes 算法中获取最多的 12 个技巧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值