【无标题】


监督学习:需要标注数据的方法 如分类 分割…
非监督学习:不需要人工标注数据 如数据量太大、人工无法完成标注。用一定规则作为“监督”,不 需要人工标注

计算机视觉问题:

image - get feature - modle - 结果
work2:hog lbp 欧式距离
work3:线性回归

最小二乘法

就是求偏导,然后使偏导为0,
1.先令w=w0
2.把w0带入model输出
3.观察模型输出与期望差
4.如果输出与期望相同,求解完成
5.如果不同,以一定规则封信w,w1=R(W)
6.把w1带入model,得到模型输出
7.转到3.
MMSE解决的问题是模型已知,参数未定的问题。
而 LS解决的是模型未知, 参数未定的问题
如何观察输出与期望差?
更新w的规则如何定?

梯度下降法:

梯度下降法可以看作是 更简单的一种 求最小二乘法最后一步解方程 的方法
梯度定义:自变量沿着负梯度方向改变,因变量会减小。
梯度下降缺点 永远在最小值震荡
梯度:y随x变化的 速度:y =f(x)
y0 = f(x0)
当 x1=x0+△x,y1=y0+g△x,g为梯度
要使y1<y0,即函数值y下降,则g
△x<0
则 △x= -ga a>0 此时,g △x = g*(-ga) = -ag2 <0
结论:若要使y的值减小(下降),只需要让x朝着-g的方向变化,即 x1 = x0-g*a
则算法中的更新公式可写为:
在这里插入图片描述
如何学习一个新模型:
1.先看使用模型的方法,模型公式
2.再看模型的参数
3.看求解方法

逻辑回归公式:

在这里插入图片描述
求解方法:
1.定义loss function
2.算法思路更新参数

实例

import torch
import torch.nn as nn
import numpy as np
from scipy import signal
import cv2
import matplotlib.pyplot as plt


def generate_data():
    # 本函数生成0-9,10个数字的图片矩阵
    image_data = []
    num_0 = torch.tensor(
        [[0, 0, 1, 1, 0, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_0)
    num_1 = torch.tensor(
        [[0, 0, 0, 1, 0, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 0, 0, 1, 0, 0],
         [0, 0, 0, 1, 0, 0],
         [0, 0, 1, 1, 1, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_1)
    num_2 = torch.tensor(
        [[0, 0, 1, 1, 0, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 0, 1, 0, 0],
         [0, 0, 1, 0, 0, 0],
         [0, 1, 1, 1, 1, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_2)
    num_3 = torch.tensor(
        [[0, 0, 1, 1, 0, 0],
         [0, 0, 0, 0, 1, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 0, 0, 0, 1, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_3)
    num_4 = torch.tensor(
        [
            [0, 0, 0, 0, 1, 0],
            [0, 0, 0, 1, 1, 0],
            [0, 0, 1, 0, 1, 0],
            [0, 1, 1, 1, 1, 1],
            [0, 0, 0, 0, 1, 0],
            [0, 0, 0, 0, 0, 0]])
    image_data.append(num_4)
    num_5 = torch.tensor(
        [
            [0, 1, 1, 1, 0, 0],
            [0, 1, 0, 0, 0, 0],
            [0, 1, 1, 1, 0, 0],
            [0, 0, 0, 0, 1, 0],
            [0, 1, 1, 1, 0, 0],
            [0, 0, 0, 0, 0, 0]])
    image_data.append(num_5)
    num_6 = torch.tensor(
        [[0, 0, 1, 1, 0, 0],
         [0, 1, 0, 0, 0, 0],
         [0, 1, 1, 1, 0, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_6)
    num_7 = torch.tensor(
        [
            [0, 1, 1, 1, 1, 0],
            [0, 0, 0, 0, 1, 0],
            [0, 0, 0, 1, 0, 0],
            [0, 0, 0, 1, 0, 0],
            [0, 0, 0, 1, 0, 0],
            [0, 0, 0, 0, 0, 0]])
    image_data.append(num_7)
    num_8 = torch.tensor(
        [[0, 0, 1, 1, 0, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 1, 1, 0, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_8)
    num_9 = torch.tensor(
        [[0, 0, 1, 1, 1, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 1, 1, 1, 0],
         [0, 1, 0, 0, 1, 0],
         [0, 0, 0, 0, 1, 0],
         [0, 0, 0, 0, 0, 0]])
    image_data.append(num_9)
    image_label = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    return image_data, image_label


def get_feature(x):
    # dx
    def s_x(img):
        kernel = np.array([[-1, 0, 1]])
        imgx = signal.convolve2d(img, kernel, boundary='symm', mode='same')
        return imgx

    # dy
    def s_y(img):
        kernel = np.array([[-1, 0, 1]]).T
        imgy = signal.convolve2d(img, kernel, boundary='symm', mode='same')
        return imgy

    # 模长
    def grad(img):
        imgx = s_x(img)
        imgy = s_y(img)
        s = np.sqrt(imgx ** 2 + imgy ** 2)
        theta = np.arctan2(imgx, imgy)
        # 显示角度值
        theta = np.degrees(theta)
        theta[theta < 0] = np.pi + theta[theta < 0]
        return s, theta

    height, width = x.shape
    gradient_magnitude, gradient_angle = grad(x)
    # cell 6*6
    cell_size = 6
    # 360°分8份
    bin_size = 8
    # 分成8份,每一份的度数
    angle_unit = 360 / bin_size
    # 取模长的绝对值
    gradient_magnitude = abs(gradient_magnitude)
    # 整张图片对应多少个cell
    cell_gradient_vector = np.zeros((int(height / cell_size), int(width / cell_size), bin_size))

    # 每个cell的特征
    def cell_gradient(cell_magnitude, cell_angle):
        # 建立一个全零的cell的特征向量
        orientation_centers = [0] * bin_size
        # cell是6*6的,遍历每一个像素点
        for k in range(cell_magnitude.shape[0]):
            for l in range(cell_magnitude.shape[1]):
                # 对应的这个像素点的模长
                gradient_strength = cell_magnitude[k][l]
                # 对应的这个像素点的角度
                gradient_angle = cell_angle[k][l]
                # 角度值除以均分的每一部分的度数,整数部分是几就在第几个bin中
                angle = int(gradient_angle / angle_unit)
                # 将模长放入对应的bin中,每个bin的值不断累加更新
                orientation_centers[angle] = orientation_centers[angle] + gradient_strength
        # 返回cell的特征向量
        return orientation_centers

    # 遍历所有cell
    for i in range(cell_gradient_vector.shape[0]):
        for j in range(cell_gradient_vector.shape[1]):
            # 取出图片上对应cell的模长
            cell_magnitude = gradient_magnitude[i * cell_size:(i + 1) * cell_size,
                             j * cell_size:(j + 1) * cell_size]
            # 取出图片上对应cell的角度
            cell_angle = gradient_angle[i * cell_size:(i + 1) * cell_size,
                         j * cell_size:(j + 1) * cell_size]
            # 将所有cell的特征向量串到一起
            cell_gradient_vector[i][j] = cell_gradient(cell_magnitude, cell_angle)

    return cell_gradient_vector


def bin2gray(x):
    # 将二值化的图像转换为灰度图
    gray_img = (x * 255).numpy().astype(np.uint8)
    # 对图像使用最近邻方法做resize, 固定图片大小为256
    gray_img = cv2.resize(gray_img, (256, 256), interpolation=cv2.INTER_LINEAR)
    return gray_img


class LinearModel(nn.Module):
    def __init__(self, in_dim, out_dim):
        super(LinearModel, self).__init__()
        # 这边将reuqires_grad=True用来标记需要自动求导的位置
        self.weights = torch.nn.Parameter(torch.DoubleTensor(in_dim, out_dim), requires_grad=True)
        nn.init.xavier_uniform_(self.weights)
        self.bias = torch.nn.Parameter(torch.DoubleTensor(out_dim), requires_grad=True)
        nn.init.zeros_(self.bias)
    # 前向计算
    def forward(self, input):
        return torch.mm(input.view(1, -1), self.weights) + self.bias


def train_model(model, data, label, max_epoch=5000, lr=0.001, device='cuda'):
    optimizer = torch.optim.SGD([{'params': model.parameters()}], lr=lr)
    loss_items = []
    for epoch in range(max_epoch):
        loss = 0
        # 梯度清零,不清零梯度会累加
        for img, lbl in zip(data, label):
            optimizer.zero_grad()
            feat = get_feature(img)
            feat = torch.from_numpy(feat).to(device)
            y_pred = model(feat)
            # l2 distance
            loss += 0.5 * (y_pred - lbl) ** 2
        # 自动计算梯度
        loss.backward()
        # 更新参数
        optimizer.step()
        print('[Epoch] {}, [Loss] {}'.format(epoch, loss.item()))
        loss_items.append(loss.item())

    # 绘制loss曲线图
    x = np.arange(0, max_epoch)
    plt.plot(x, loss_items, color='red', linewidth=1)

    plt.title("Epoch-Loss Curve")
    plt.savefig("./loss.png")
    print("loss曲线图已保存到loss.png文件")

# 根据特征预测图片
def inference(feat, model, device='cuda'):
    return model(torch.from_numpy(feat).to(device))



if __name__ == "__main__":
    # 先对模型进行训练
    image_data, image_label = generate_data()

    # 放大生成的图片
    image_data = [bin2gray(x) for x in image_data]

    num_sample = len(image_data)
    num_feat = get_feature(image_data[0]).flatten().shape[0]
    learning_rate = 1e-9
    num_epoch = 500
    device = 'cpu' if not torch.cuda.is_available() else 'cuda'
    model = LinearModel(in_dim=num_feat, out_dim=1).to(device)
    train_model(model, image_data, image_label, max_epoch=num_epoch, lr=learning_rate, device=device)

    print("对每张图片进行识别")
    for i in range(0, num_sample):
        x = image_data[i]
        # 对当前图片提取特征
        feature = get_feature(x)
        # 对提取到得特征进行分类
        y = inference(feature, model, device=device)
        # 打印出分类结果
        print("图像[%s]得分类结果是:[%s]" % (i, y.item()))




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值