首先可视化待训练数据
import numpy as np
import matplotlib.pyplot as plt
# 手写实现单自变量的线性回归问题,实现直线的拟合,f(x) = a * x + b
# 线性回归问题, 有监督学习模型
# 训练样本数据:1、线性模型 2、标签数据
xTrain = np.array([[6],
[8],
[10],
[14],
[18]])
yTrain = np.array([7, 8, 13, 17.5, 18])
plt.scatter(xTrain.flatten(), yTrain)
plt.show()
未开始训练的初始线
import numpy as np
import matplotlib.pyplot as plt
# 手写实现单自变量的线性回归问题,实现直线的拟合,f(x) = a * x + b
# 线性回归问题, 有监督学习模型
# 训练样本数据:1、线性模型 2、标签数据
xTrain = np.array([[6],
[8],
[10],
[14],
[18]])
yTrain = np.array([7, 8, 13, 17.5, 18])
# 使用梯度下降算法手写实现线性回归
# 损失函数(cost function)
# 定义模型函数原型
def predict(X, w, b):
return X.dot(w) + b
pass
# 定义损失函数,均方误差MSE mean square error
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum((py - y)**2)/2/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y)/len(X) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.01, tel = 0.0000000001, times = 1000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tel:
break
t += 1
pass
pass
w = np.array([[2]])
b = 1
r = predict(xTrain, w, 1)
g_w, g_b = gradient(xTrain, w, b, yTrain)
print(r)
plt.plot(xTrain.flatten(), r.flatten())
# 画图显示
plt.scatter(xTrain.flatten(), yTrain)
plt.show()
加入训练函数后的代码:
import numpy as np
import matplotlib.pyplot as plt
# 手写实现单自变量的线性回归问题,实现直线的拟合,f(x) = a * x + b
# 线性回归问题, 有监督学习模型
# 训练样本数据:1、线性模型 2、标签数据
xTrain = np.array([[6],
[8],
[10],
[14],
[18]])
yTrain = np.array([7, 8, 13, 17.5, 18])
# 使用梯度下降算法手写实现线性回归
# 损失函数(cost function)
# 定义模型函数原型
def predict(X, w, b):
return X.dot(w) + b
pass
# 定义损失函数,均方误差MSE mean square error
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum((py - y)**2)/2/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y)/len(X) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.01, tel = 0.0000000001, times = 1000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tel:
break
t += 1
pass
return w, b
pass
w = np.array([[2]])
b = 1
r = predict(xTrain, w, 1)
g_w, g_b = gradient(xTrain, w, b, yTrain)
print(r)
plt.plot(xTrain.flatten(), r.flatten(), 'b--')
# 训练模型
w,b = train(xTrain, w, b, yTrain)
py = predict(xTrain, w, 1)
plt.plot(xTrain.flatten(), py.flatten(), 'r--')
# 画图显示
plt.scatter(xTrain.flatten(), yTrain)
plt.show()
感觉效果有点差,调整参数alpha,继续看训练效果
可以使用sklearn简单实现线性回归
# 使用sklearn库实现线性回归模型
# 要想学会算法的原理和思想,必须从数学开始,从看懂数学原理入手,然后代码实现,才能真正理解
from sklearn.linear_model import LinearRegression
import numpy as np
xTrain = np.array([[6],
[8],
[10],
[14],
[18]])
yTrain = np.array([7, 8, 13, 17.5, 18])
mode1 = LinearRegression()
mode1.fit(xTrain, yTrain)
print(mode1.predict([[20]]))
print(mode1.intercept_) # 截距
print(mode1.coef_) # 斜率
二维平面拟合,注意这里使用3D可视化工具,如果matplotlib版本过高,无法绘制出图形,可以降低版本号(3.5.2)再绘制。
# 拟合平面
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 手写实现多自变量的线性回归问题,实现直线的拟合,f(x) = a * x1 + b * x2 + c
# 线性回归问题, 有监督学习模型
# 训练样本数据:1、线性模型 2、标签数据
xTrain = np.array([[6, 2],
[8, 1],
[10, 0],
[14, 2],
[18, 0]])
yTrain = np.array([7, 8, 13, 17.5, 18])
# 通用算法
# 使用梯度下降算法手写实现线性回归
# 损失函数(cost function)
# 定义模型函数原型
def predict(X, w, b):
return X.dot(w) + b
pass
# 定义损失函数,均方误差MSE mean square error
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum((py - y)**2)/2/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y).reshape(-1, 1) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.0001, tel = 0.0000000001, times = 10000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
print(loss0)
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tel:
break
t += 1
pass
return w, b
pass
w = np.array([[2],
[1]])
b = 1
r = predict(xTrain, w, b)
g_w, g_b = gradient(xTrain, w, b, yTrain)
print(r)
# 训练模型
w,b = train(xTrain, w, b, yTrain)
py = predict(xTrain, w, b)
# 可视化算法的模型效果
# 观察模型效果
figure = plt.figure()
ax = Axes3D(figure)
ax.scatter3D(xTrain[:, 0], xTrain[:, 1], yTrain)
plt.show()
# 拟合平面
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 手写实现多自变量的线性回归问题,实现直线的拟合,f(x) = a * x1 + b * x2 + c
# 线性回归问题, 有监督学习模型
# 训练样本数据:1、线性模型 2、标签数据
xTrain = np.array([[6, 2],
[8, 1],
[10, 0],
[14, 2],
[18, 0]])
yTrain = np.array([7, 8, 13, 17.5, 18])
# 通用算法
# 使用梯度下降算法手写实现线性回归
# 损失函数(cost function)
# 定义模型函数原型
def predict(X, w, b):
return X.dot(w) + b
pass
# 定义损失函数,均方误差MSE mean square error
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum((py - y)**2)/2/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y).reshape(-1, 1) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.0001, tel = 0.0000000001, times = 10000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
print(loss0)
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tel:
break
t += 1
pass
return w, b
pass
w = np.array([[2],
[1]])
b = 1
r = predict(xTrain, w, b)
g_w, g_b = gradient(xTrain, w, b, yTrain)
print(r)
# 训练模型
w,b = train(xTrain, w, b, yTrain)
py = predict(xTrain, w, b)
# 可视化算法的模型效果
# 观察模型效果
figure = plt.figure()
ax = Axes3D(figure)
ax.scatter3D(xTrain[:, 0], xTrain[:, 1], yTrain, c = 'r')
points = np.arange(0, 30, 0.5)
vx, vy = np.meshgrid(points, points)
xPoints = np.array([vx.flatten(), vy.flatten()]).T
py = predict(xPoints, w, b)
ax.plot_surface(vx, vy, py.reshape(vx.shape))
plt.show()
接下来实现高阶拟合,首先模拟出需要的实验数据,然后进行实验:
# 高阶拟合
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 通用算法
# 使用梯度下降算法手写实现线性回归
# 损失函数(cost function)
# 定义模型函数原型
def predict(X, w, b):
return X.dot(w) + b
pass
# 定义损失函数,均方误差MSE mean square error
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum((py - y)**2)/2/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y).reshape(-1, 1) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.0001, tel = 0.0000000001, times = 10000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
print(loss0)
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tel:
break
t += 1
pass
return w, b
pass
# 假设拟合 :f(x1, x2) = w1*x1^2 + w2*x2^2 + w0
# 数据需要符合特定的线性规律,才能使用线性拟合
# 实验1,假设拟合如下方程:f(x1, x2) = 2*x1^2 + 3*x2*x1 + x2^2 + 10
def makeY(xTrain):
# 这里是为了得到实验的yTrain数据,注意还要在最后得到的数据上加一些偏移,以求更逼真的实验
for row in xTrain:
return np.array([2 * row[0]**2 + 3 * row[0] * row[1] + row[1] ** 2 + 10 + np.random.uniform(-1, 1) for row in xTrain])
pass
pass
xTrain = np.array([[1, 3],
[5, 7],
[2, 5],
[5, 10],
[1.5, 9]])
yTrain = makeY(xTrain)
print(yTrain)
# 绘出分布点
figure = plt.figure()
ax = Axes3D(figure)
figure.add_axes(ax)
ax.scatter3D(xTrain[:, 0], xTrain[:, 1], yTrain, c='r')
plt.show()
算法的效果与实验的数据数量也有关系,实验代码如下:
# 高阶拟合
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 通用算法
# 使用梯度下降算法手写实现线性回归
# 损失函数(cost function)
# 定义模型函数原型
def predict(X, w, b):
return X.dot(w) + b
pass
# 定义损失函数,均方误差MSE mean square error
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum((py - y)**2)/2/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y).reshape(-1, 1) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.001, tel = 0.00000000001, times = 200000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
print(loss0)
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tel:
break
t += 1
pass
return w, b
pass
# 假设拟合 :f(x1, x2) = w1*x1^2 + w2*x2^2 + w0
# 数据需要符合特定的线性规律,才能使用线性拟合
# 实验1,假设拟合如下方程:f(x1, x2) = 2*x1^2 + 3*x2*x1 + x2^2 + 10
def makeY(xTrain):
# 这里是为了得到实验的yTrain数据,注意还要在最后得到的数据上加一些偏移,以求更逼真的实验
for row in xTrain:
return np.array([2 * row[0]**2 + 3 * row[0] * row[1] + row[1] ** 2 + 4 * row[0] + 10 + np.random.uniform(-1, 1) for row in xTrain])
pass
pass
xTrain = np.array([[1.5, 3],
[0.5, 2],
[3, 5],
[5, 2],
[2.5, 1],
[1.5, 2],
[2, 1],
[1.1, 4],
[4, 1.1]])
yTrain = makeY(xTrain)
print(yTrain)
# 扩维降阶(属于工程方法),样本数量不够,也会影响算法的结果
xNewTrain = np.array([[2.25, 4.5, 9, 1.5],
[0.25, 1, 4, 0.5],
[9, 15, 25, 3],
[25, 10, 4, 5],
[6.25, 2.5, 1, 2.5],
[2.25, 3, 4, 1.5],
[4, 2, 1, 2],
[1.21, 4.4, 16, 1.1],
[16, 4.4, 1.21, 4]])
w = np.array([[0.5],
[0.5],
[0.2],
[0.6]])
b = 0.1
w, b = train(xNewTrain, w, b, yTrain)
print(w)
print(b)
# 绘出分布点
figure = plt.figure()
ax = Axes3D(figure)
figure.add_axes(ax)
ax.scatter3D(xTrain[:, 0], xTrain[:, 1], yTrain, c='r')
# 绘制曲面(比较复杂)
xPoints = np.arange(-6, 6, 0.2)
vx, vy = np.meshgrid(xPoints, xPoints)
xxTrain = np.array([vx.flatten(), vy.flatten()]).T
xxNewTrain = np.array([xxTrain[:, 0]**2, xxTrain[:, 0] * xxTrain[:, 1], xxTrain[:, 1]**2, xxTrain[:, 0]]).T
py = predict(xxNewTrain, w, b)
ax.plot_surface(vx, vy, py.reshape(vx.shape))
plt.show()
可以看到最后的参数是比较接近2, 3, 1, 4, 10这几个参数的,训练效果比较理想。
逻辑回归
逻辑回归代码:
# 手写实现逻辑回归分类算法,并且实现二分类任务
# 逻辑回归属于监督学习模型
import numpy as np
# 激活函数
def sigmoid(x):
return 1/(1+np.exp(-x))
pass
# 模型函数, 与线性回归不同,在模型函数后加了一个激活函数
def predict(X, w, b):
return sigmoid(X.dot(w) + b)
pass
# 定义交叉熵损失函数
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum(-y * np.log(py) - (1-y) * np.log(1-py))/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y).reshape(-1, 1) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.1, tol = 1e-10, times = 200000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
print(loss0)
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tol:
break
t += 1
pass
return w, b
pass
w = np.array([[2],
[2]])
b = 0
xTrain = np.array([[30, 50],
[70, 80],
[60, 40],
[70, 90],
[90, 70],
[50, 40],
[40, 60],
[30, 90],
[90, 80],
[70, 90],
[10, 20],
[50, 50],
[61, 62]])
xTrain = xTrain/100
yTrain = np.array([0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1])
w, b = train(xTrain, w, b, yTrain)
result = predict(xTrain, w, b)
print(result)
result = np.where(result > 0.5, 1, 0)
print(result.flatten())
使用测试集验证后:
# 手写实现逻辑回归分类算法,并且实现二分类任务
# 逻辑回归属于监督学习模型
import numpy as np
# 激活函数
def sigmoid(x):
return 1/(1+np.exp(-x))
pass
# 模型函数, 与线性回归不同,在模型函数后加了一个激活函数
def predict(X, w, b):
return sigmoid(X.dot(w) + b)
pass
# 定义交叉熵损失函数
def loss(X, w, b, y):
py = predict(X, w, b).flatten()
return np.sum(-y * np.log(py) - (1-y) * np.log(1-py))/len(X)
pass
def gradient(X, w, b, y):
py = predict(X, w, b).flatten()
# g对w的导数
g_w = X.T.dot(py - y).reshape(-1, 1) # np.sum(X[:, 0] + (py-y)/len(x))
# g对b的导数
g_b = np.sum(py - y) / len(X)
return g_w, g_b
pass
# 定义训练训练函数, 梯度下降算法
def train(X, w, b, y, alpha=0.1, tol = 1e-10, times = 200000):
t = 0
while t < times:
loss0 = loss(X, w, b, y) # 计算损失
print(loss0)
g_w, g_b = gradient(X, w, b, y) # 求w和b的导数
w = w - alpha*g_w # 梯度更新
b = b - alpha*g_b # 梯度更新
loss1 = loss(X, w, b, y)
if np.absolute(loss0 -loss1) < tol:
break
t += 1
pass
return w, b
pass
w = np.array([[2],
[2]])
b = 0
xTrain = np.array([[30, 50],
[70, 80],
[60, 40],
[70, 90],
[90, 70],
[50, 40],
[40, 60],
[30, 90],
[90, 80],
[70, 90],
[10, 20],
[50, 50],
[61, 62]])
xTrain = xTrain/100
yTrain = np.array([0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1])
w, b = train(xTrain, w, b, yTrain)
result = predict(xTrain, w, b)
print(result)
result = np.where(result > 0.5, 1, 0)
print(result.flatten())
# 预测
xTest = np.array([[30, 30],
[100, 100],
[40, 60]])
xTest = xTest/100
yTest = ([0, 1, 0])
result = predict(xTest, w, b)
result = np.where(result > 0.5, 1, 0).flatten()
print(result)
# 使用测试集验证,计算准确率
acc = 1-np.count_nonzero(yTest - result) / len(yTest)
print("准确率: %.2f%%" % (acc * 100))
调用sklearn库的算法:
from sklearn.linear_model import LogisticRegression
import numpy as np
# 训练样本
xTrain = np.array([[30, 50],
[70, 80],
[60, 40],
[70, 90],
[90, 70],
[50, 40],
[40, 60],
[30, 90],
[90, 80],
[70, 90],
[10, 20],
[50, 50],
[61, 62]])
yTrain = np.array([0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1])
model = LogisticRegression()
model.fit(xTrain, yTrain)
result = model.predict(xTrain)
print(result)
# 预测
xTest = np.array([[30, 30],
[100, 100],
[40, 60]])
yTest = np.array([0, 1, 0])
print(model.predict(xTest))
print(model.score(xTest, yTest)) # 准确率