1.回归与分类
线性回归
- 定义:利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。
-
要素:训练集、输出数据、拟合函数(模型)、训练数据的条目数
-
适用问题:房价与影响因素、GDP与人均年度可支配收入等线性关系
-
学习过程:
代码示例
①生成示例数据
clear all; close all; clc;
sigma = 1; m = 100;
d = 1; % 1维属性的情形
w1 = 3; b = 2; % 生成数据的目标函数参数(存在但未知)
tilde_W = [w1; b];
noises = normrnd(0,sigma,[m, 1]);
samples = 10*rand(m,d);
X = [samples, ones(m,1)];
Y = X*tilde_W + noises;
save('data_01.mat','samples','X','Y','m','tilde_W','sigma','d');
②回归
clear all; close all; clc;
load('data_01.mat','samples','X','Y','m','tilde_W','sigma','d');
figure; plot(samples,Y,'b.'); % 2维属性时用plot3函数绘制
axis([0 10 0 35]);
xlabel('x');
ylabel('y');
hold on;
RY([1:m],1)=0;%初始化
WN=pinv(X);
Wlin=WN*Y;
sum=0;
for i=1:m
RY(i)=Wlin(1)*X(i,1)+Wlin(2)*X(i,2);
end
for i=1:m
sum = sum+(RY(i)-Y(i))^2;
end
Ein=sum/m;
REin=sigma^2*(1-(d+1)/m);
REout=sigma^2*(1+(d+1)/m);
%输入x为1维时的绘图程序
hat_x = [0:0.1:10]';
hat_X = [hat_x ones(length(hat_x),1)];
hat_Y = hat_X*Wlin;
plot(hat_x,hat_Y,'k');
axis([0 10 0 35]);
运行结果
线性二分类
-
定义:线性分类器则透过特征的线性组合来做出分类决定,以达到此种目的。简言之,样本通过直线(或超平面)可分
-
线性分类器输入:特征向量
-
输出:所属类别。
二分类问题,输出0或1;多分类问题,输出属于某类的概率
-
线性分类与线性回归的差别:
输出意义不同:属于某类的概率<——>回归具体值
参数意义不同:最佳分类直线<——>最佳拟合直线
维度不同:一维的回归<——>二维的分类
-
Sigmoid函数:
-
梯度下降法:梯度下降法(Gradient Descent)是一种优化算法,是迭代法的一种,用于最小化损失函数。它通过不断地更新模型参数,以逼近损失函数的最小值。梯度下降法的核心思想是通过计算损失函数的梯度(Gradient),然后根据梯度的方向调整模型参数,从而逐步减小损失值。
代码示例
% 生成示例数据
num_samples = 100; % 样本数量
features = 2; % 特征数量
% 生成两个类别的随机数据
class_1 = randn(num_samples, features) + 1; % 第一类样本
class_2 = randn(num_samples, features) - 1; % 第二类样本
% 合并样本和标签
X = [class_1; class_2]; % 特征矩阵
y = [ones(num_samples, 1); -ones(num_samples, 1)]; % 标签
% 在数据中添加偏置项(截距)
X = [ones(size(X, 1), 1) X];
% 初始化权重
weights = randn(size(X, 2), 1);
% 定义学习率和迭代次数
learning_rate = 0.01;
num_iterations = 1000;
% 训练模型
for iter = 1:num_iterations
% 计算预测
predictions = X * weights;
% 应用阈值函数(比如,符号函数)来预测类别
predicted_labels = sign(predictions);
% 计算误差
errors = (predicted_labels ~= y);
% 计算梯度
gradient = X' * (errors .* y);
% 更新权重
weights = weights - learning_rate * gradient;
end
% 打印最终的权重
disp('Final weights:');
disp(weights);
% 绘制决策边界
x1 = linspace(min(X(:, 2)), max(X(:, 2)), 100);
x2 = (-weights(1) - weights(2) * x1) / weights(3);
plot(class_1(:, 1), class_1(:, 2), 'ro', class_2(:, 1), class_2(:, 2), 'bo', x1, x2, 'k-');
xlabel('Feature 1');
ylabel('Feature 2');
title('Linear Binary Classification');
legend('Class 1', 'Class 2', 'Decision Boundary');
运行结果
指数回归
代码示例
% 示例数据
x = [1, 2, 3, 4, 5]; % 自变量
y = [3.2, 7.1, 14.2, 28.4, 56.8]; % 因变量
% 拟合指数函数模型: y = a * exp(b * x)
% 使用最小二乘法拟合指数函数模型
A = [ones(size(x')) x']; % 构建设计矩阵
log_y = log(y); % 对因变量取对数
coefficients = A \ log_y'; % 通过线性回归求解系数
% 提取拟合系数
a = exp(coefficients(1));
b = coefficients(2);
% 输出拟合的指数函数模型
disp('拟合的指数函数模型为:');
disp(['y = ', num2str(a), ' * exp(', num2str(b), ' * x)']);
% 绘制原始数据和拟合曲线
xfit = linspace(min(x), max(x), 100); % 创建用于绘制拟合曲线的新自变量值
yfit = a * exp(b * xfit); % 计算拟合曲线的因变量值
figure;
plot(x, y, 'bo', xfit, yfit, 'r-');
xlabel('x');
ylabel('y');
title('Exponential Regression');
legend('原始数据', '拟合曲线');
运行结果
Softmax多分类回归
代码示例
% 生成示例数据
num_samples = 200; % 样本数量
num_classes = 3; % 类别数量
features = 2; % 特征数量
% 生成多类别的随机数据
class_1 = randn(num_samples, features) + [2, 2];
class_2 = randn(num_samples, features) + [-2, 2];
class_3 = randn(num_samples, features) + [0, -2];
% 合并样本和标签
X = [class_1; class_2; class_3]; % 特征矩阵
y = [ones(num_samples, 1); 2 * ones(num_samples, 1); 3 * ones(num_samples, 1)]; % 标签
% 在数据中添加偏置项(截距)
X = [ones(size(X, 1), 1) X];
% 初始化权重
num_features = size(X, 2);
num_classes = max(y);
weights = randn(num_features, num_classes);
% 定义学习率和迭代次数
learning_rate = 0.01;
num_iterations = 1000;
% Softmax 函数
softmax = @(z) exp(z) ./ sum(exp(z), 2);
% 训练模型
for iter = 1:num_iterations
% 计算预测
predictions = X * weights;
% 计算 Softmax 输出
probs = softmax(predictions);
% 计算交叉熵损失
num_samples = size(X, 1);
loss = -sum(log(probs(sub2ind(size(probs), 1:num_samples, y')))) / num_samples;
% 计算梯度
probs(sub2ind(size(probs), 1:num_samples, y')) = probs(sub2ind(size(probs), 1:num_samples, y')) - 1;
gradient = X' * probs;
% 更新权重
weights = weights - learning_rate * gradient;
end
% 打印最终的权重
disp('Final weights:');
disp(weights);
% 预测类别
[~, predicted_labels] = max(X * weights, [], 2);
% 绘制分类结果
scatter(class_1(:, 1), class_1(:, 2), 'r', 'filled');
hold on;
scatter(class_2(:, 1), class_2(:, 2), 'g', 'filled');
scatter(class_3(:, 1), class_3(:, 2), 'b', 'filled');
xlabel('Feature 1');
ylabel('Feature 2');
title('Softmax Classification Result');
legend('Class 1', 'Class 2', 'Class 3');
hold off;
运行结果
2.神经网络基础
单神经元模型
激活函数![f(x)](https://latex.csdn.net/eq?f%28x%29)
用于引入非线性特性,使得神经网络能够学习非线性模式。
常用的单神经元模型的激活函数包括:
非对称型Sigmoid函数:
对称型Sigmoid函数:
对称型阶跃函数(具有阶跃作用函数的神经元,称为阈值逻辑单元):
- Hebb规则:连接权值的调整量与输入输出的乘积成正比
感知机模型
Rosenblatt 在 1957 年提出的一种简单的二元分类器,其结构与单神经元完全相同,是神经网络的基础模型。
代码示例
% 生成示例数据
class_1 = [1, 2; 2, 3; 2, 1];
class_2 = [3, 4; 4, 5; 5, 3];
X = [class_1; class_2];
y = [ones(size(class_1, 1), 1); -ones(size(class_2, 1), 1)];
% 初始化权重和偏置项
weights = randn(1, size(X, 2));
bias = randn();
% 定义学习率和迭代次数
learning_rate = 0.01;
num_iterations = 1000;
% 训练感知机模型
for iter = 1:num_iterations
% 随机排列数据
idx = randperm(length(y));
X = X(idx, :);
y = y(idx);
for i = 1:length(y)
% 计算预测值
prediction = X(i, :) * weights' + bias;
% 应用阈值函数来预测类别
if prediction >= 0
predicted_label = 1;
else
predicted_label = -1;
end
% 更新权重和偏置项
if predicted_label ~= y(i)
weights = weights + learning_rate * y(i) * X(i, :);
bias = bias + learning_rate * y(i);
end
end
end
% 打印最终的权重和偏置项
disp('Final weights:');
disp(weights);
disp('Final bias:');
disp(bias);
% 绘制分类线
x1 = min(X(:, 1)):0.1:max(X(:, 1));
x2 = (-bias - weights(1) * x1) / weights(2);
plot(class_1(:, 1), class_1(:, 2), 'ro', class_2(:, 1), class_2(:, 2), 'bo', x1, x2, 'k-');
xlabel('Feature 1');
ylabel('Feature 2');
title('Perceptron Classification');
legend('Class 1', 'Class 2', 'Decision Boundary');
运行结果
多层感知机
-
Minsky于1969年提出了XOR问题(线性不可分),单层感知机无法分类
解决方法:使用多层感知机
-
结构:
三层感知器可识别任意凸多边形或无界的凸区域,更多层感知器网络,可识别更为复杂的图形。
- 定理1 若隐层节点(单元)可任意设置,用三层阈值节点的网络,可以实现任意的二值逻辑函数。
- 定理2 若隐层节点(单元)可任意设置,用三层S型非线性特性节点的网络,可以一致逼近紧集上的连续函数或按范数逼近紧集上的平方可积函数。
BP算法
多层感知机算法是一种多层前馈网络,如果每一个神经元都连接到上一层的所有神经元(除输出层外),则称为全连接网络。多层前馈网络的反向传播(BP)学习算法,简称BP算法,是有导师的学习,它是梯度下降法在多层前馈网中的应用,其结构如下:
BP学习算法由正向传播和反向传播组成:
①正向传播是输入信号从输入层经隐层,传向输出层,若输出层得到了期望的输出,则学习算法结束;否则,转至反向传播。
②反向传播是将误差(样本输出与网络输出之差)按原联接通路反向计算,由梯度下降法调整各层节点的权值和阈值,使误差减小。
优点
学习完全自主;可逼近任意非线性函数
缺点
算法非全局收敛;收敛速度慢;学习速率的选择;神经网络如何设计(层数、节点数)
代码示例(多分类)
clear all; close all; clc;
% 生成示例数据
num_samples = 100; % 样本数量
num_classes = 3; % 类别数量
features = 2; % 特征数量
% 生成多类别的随机数据
class_1 = randn(num_samples, features) + [2, 2];
class_2 = randn(num_samples, features) + [-2, 2];
class_3 = randn(num_samples, features) + [0, -2];
% 合并样本和标签
X = [class_1; class_2; class_3]; % 特征矩阵
y = [ones(num_samples, 1); 2 * ones(num_samples, 1); 3 * ones(num_samples, 1)]; % 标签
% 转换标签为独热编码
Y_onehot = zeros(length(y), num_classes);
for i = 1:length(y)
Y_onehot(i, y(i)) = 1;
end
% 初始化神经网络参数
input_layer_size = features;
hidden_layer_size = 5; % 隐藏层神经元数量
output_layer_size = num_classes;
epsilon_init = 0.12; % 初始化权重时的范围
% 随机初始化权重
Theta1 = rand(hidden_layer_size, input_layer_size + 1) * 2 * epsilon_init - epsilon_init;
Theta2 = rand(output_layer_size, hidden_layer_size + 1) * 2 * epsilon_init - epsilon_init;
% 训练神经网络模型(使用反向传播算法)
lambda = 0.1; % 正则化参数
alpha = 0.01; % 学习率
num_iterations = 1000; % 迭代次数
for iter = 1:num_iterations
% 前向传播
a1 = [ones(size(X, 1), 1) X]; % 添加偏置项
z2 = a1 * Theta1';
a2 = sigmoid(z2);
a2 = [ones(size(a2, 1), 1) a2]; % 添加偏置项
z3 = a2 * Theta2';
a3 = sigmoid(z3);
h = a3;
% 计算损失函数(交叉熵损失)
J = -(1/num_samples) * sum(sum(Y_onehot .* log(h) + (1 - Y_onehot) .* log(1 - h)));
% 添加正则化项
J = J + (lambda / (2 * num_samples)) * (sum(sum(Theta1(:, 2:end).^2)) + sum(sum(Theta2(:, 2:end).^2)));
% 反向传播
delta3 = a3 - Y_onehot;
delta2 = (delta3 * Theta2(:, 2:end)) .* sigmoidGradient(z2);
% 计算梯度
Delta2 = delta3' * a2;
Delta1 = delta2' * a1;
% 正则化梯度
Theta2_grad = (1/num_samples) * Delta2 + (lambda/num_samples) * [zeros(size(Theta2, 1), 1) Theta2(:, 2:end)];
Theta1_grad = (1/num_samples) * Delta1 + (lambda/num_samples) * [zeros(size(Theta1, 1), 1) Theta1(:, 2:end)];
% 更新参数
Theta2 = Theta2 - alpha * Theta2_grad;
Theta1 = Theta1 - alpha * Theta1_grad;
end
% 预测类别
pred = predict(Theta1, Theta2, X);
% 绘制分类结果
plotData(X, pred);
xlabel('Feature 1');
ylabel('Feature 2');
title('Classification Result');
% 辅助函数:sigmoid 函数
function g = sigmoid(z)
g = 1 ./ (1 + exp(-z));
end
% 辅助函数:sigmoid 函数的梯度
function g = sigmoidGradient(z)
g = sigmoid(z) .* (1 - sigmoid(z));
end
% 辅助函数:预测类别
function pred = predict(Theta1, Theta2, X)
m = size(X, 1);
num_labels = size(Theta2, 1);
a1 = [ones(m, 1) X];
z2 = a1 * Theta1';
a2 = sigmoid(z2);
a2 = [ones(size(a2, 1), 1) a2];
z3 = a2 * Theta2';
a3 = sigmoid(z3);
[~, pred] = max(a3, [], 2);
end
% 辅助函数:绘制分类结果
function plotData(X, y)
scatter(X(y == 1, 1), X(y == 1, 2), 'r', 'filled');
hold on;
scatter(X(y == 2, 1), X(y == 2, 2), 'g', 'filled');
scatter(X(y == 3, 1), X(y == 3, 2), 'b', 'filled');
hold off;
legend('Class 1', 'Class 2', 'Class 3');
end
运行结果
3.性能优化
常用技巧
- 模型初始化:在[-1,1]区间按均值or高斯分布初始化;Xavier初始化。
- 训练数据、验证数据、测试数据,按照70/60%、15/20%、15/20%分配,数据较多时训练和验证数据可适当减少。
- K折交叉验证:原始训练数据被分成K个不重叠的子集。然后执行K次模型训练和验证,每次在K-1个子集上进行训练,并在剩余的一个子集(在该轮中没有用于训练的子集)上进行验证。最后,通过对K次实验的结果取平均来估计训练和验证误差。
- 注意:欠拟合(误差一直较大)、过拟合(在训练集误差小,测试集误差大)
- 权重衰减:L2正则化,约束权值不能过大
- Dropout(暂退):在整个训练过程的每一次迭代中,标准暂退法包括在计算下一层之前将当前层中的一些节点置零
-
动量法
-
有效改善收敛速度,避免一些陷入局部极小值
自适应梯度算法
-
自适应调整学习速率,加速收敛