Deep learning for Computer Vision with Python笔记(5)构建线性分类器并优化参数

上文链接:

​​​​​​​Deep learning for Computer Vision with Python(1)从零开始入门计算机视觉

Deep learning for Computer Vision with Python 笔记(2)图像基础_冰淇淋2333的博客-CSDN博客

Deep learning for Computer Vision with Python笔记(3)图像数据集介绍_冰淇淋2333的博客-CSDN博客

Deep learning for Computer Vision with Python笔记(4)构建KNN图像分类器_冰淇淋2333的博客-CSDN博客

什么是参数学习?

对于一个给定的模型,对于必要的参数进行定义。

这里的参数是广义的定义,包括所有影响模型训练的因素:数据,评分函数,损失函数,权重,以及偏差。

1. 线性分类器的介绍:从图像到标签

整个线性分类器 的过程可以用下图来表示。图像矩阵×权重矩阵+b,得到最终的y是一个n维向量,n是标签的个数。w的大小是由图像大小决定的。

线性分类器的好处有:1. 一旦数据和标签定下来,我们只需要考虑w和b对于模型的影响。2. 预测的效率非常高。

2. python实现线性分类器的图像分类

1. 构建图像

初始化W,b;加载图片并展平为3×3072维度;

import numpy as np
import cv2

labels = ["dog", "cat", "panda"]
np.random.seed(1)

W = np.random.randn(3, 3072) # 3072 = 3 * 32 * 32
b = np.random.rand(3)

# 加载图像,调整大小,转成numpy,展平
orig = cv2.imread("test.jpg")
image = cv2.resize(orig, (32, 32)).flatten()

W:(3*3072), image:(3072*1), 所以相乘后结果为(3*1). 目标有多少类,W的行就取多少。

2. 线性计算,并计算精度

# 线性计算
scores = W.dot(image) + b

for (label, score) in zip(labels, scores): # 同时迭代两个数组:zip合并
    print("[INFO] {}: {:.2f}".format(label, score))

cv2.putText(orig, "Label: {}".format(labels[np.argmax(scores)]), (10,30), cv2.FONT_HERSHEY_SIMPLEX,
            0.9, (0, 255, 0), 2)
cv2.imshow("Image", orig)
cv2.waitKey(0)

获得结果: 

以上的例子是我们通过随机方式手动初始化W和b,接下来我们将介绍优化和梯度下降,通过优化的方式学习到最优的W和b。

3. 优化策略:梯度下降法

如图所示,梯度下降法是当权重不断增大时,损失函数的图像有波峰和波谷。每个波峰是局部最大值,每个波谷是局部最小值。局部最小值中损失最小的是全局最小值,我们的理想状态就是找到这个全局最小值时参数的取值。

然而,在真正的学习过程中,这张图是不可见的,无法可视化,也就很难找到这个全局最小值。实际上,我们可以把学习过程比作一个碗,机器人在碗里行走,试图找到碗的最低点(碗是三维的,而实际问题可能有几万维)。机器人的初始位置是随机的,他需要通过调整自己的方向,每一步都朝着下坡的方向走,直到达到碗底。他并不知道哪个方向离碗底最近,只能计算出损失最小的方向,尝试优化参数。

 这个理论成立的前提是:损失函数是一个凸函数,也就是说它只要有局部最小值,那么局部最小值就是全局最小值。但是,大多数处理的问题几乎都不是平整的凸函数,而是有多个波峰和波谷。但是,我们仍然使用梯度下降法,是因为这个方法已经足够好了,尽管不是全局最小,但是结果的实践是足够的。

在python中应用梯度下降法训练线性分类器并评估结果:

from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import numpy as np
import argparse

def sigmoid_activation(x):
# sigmod 激活函数
    return 1.0 / (1 + np.exp(-x))

def predict(X, W):
    preds = sigmoid_activation(X.dot(W))
    preds[preds <= 0.5] = 0
    preds[preds > 0] = 1

    return preds

# 输入参数:epochs和学习率
ap = argparse.ArgumentParser()
ap.add_argument("-e","--epochs", type=float, default=100, help="# of epochs")
ap.add_argument("-a", "--alpha", type=float, default=0.01, help="learning rate") # 梯度下降的学习率
args = vars(ap.parse_args())

# 聚类,生成1000个数据点,两类数据,特征维度为2
(X, y) = make_blobs(n_samples=1000, n_features=2, centers=2, cluster_std=1.5, random_state=1)

# 插入一个常数列作为偏置(b)
y = y.reshape((y.shape[0], 1))

# np.c_:左右连接两个矩阵
X = np.c_[X, np.ones((X.shape[0]))]

(trainX, testX, trainY, testY) = train_test_split(X, y, test_size=0.5, random_state=42)

# 初始化权重矩阵:
print("[INFO] training...")
W = np.random.randn(X.shape[1], 1)
losses = []

# 训练:梯度下降
for epoch in np.arange(0, args["epochs"]):
    preds = sigmoid_activation(trainX.dot(W))
    error = preds - trainY
    loss = np.sum(error ** 2)
    losses.append(loss) # 最小二乘误差

    # 计算梯度,更新权重矩阵
    gradient = trainX.T.dot(error)
    W += -args["alpha"] * gradient

    if epoch == 0 or (epoch + 1) % 5 == 0:
        print("[INFO] epoch={}, losses={:.7f}".format(int(epoch + 1), loss))

# 测试结果
print("[INFO] evaluating...")
preds = predict(testX, W)
print(classification_report(testY, preds))

# 绘制测试数据
plt.style.use("ggplot")
plt.figure()
plt.title("Data")
plt.scatter(testX[:, 0], testX[:, 1], marker="o", c=testY, s=30)

# 损失数据可视化
plt.style.use("ggplot")
plt.figure()
plt.plot(np.arange(0, args["epochs"]), losses)
plt.title("Training loss")
plt.xlabel("Epoch #")
plt.ylabel("Loss")
plt.show()

结果:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值