手把手教你K最近邻分类器分类CIFAR-10

2023-11-19

KNN算法全称为k-Nearest Neighbor Classifier,即k最近邻分类器。它可以看作是Nearest Neighbor Classifier最近邻分类器的加强版,无论是最近邻分类器还是k最近邻分类器,其原理都比较简单,其算法在CIFAR-10图像分类的效果上其正确率远低于人类识别图像的正确率(约94%),但也略高于随即猜测的10%的正确率(CIFAR-10有10个分类,随机猜测的正确率为10%)。

基于最近邻分类器的CIFAR-10的图像分类

CIFAR-10可视化 可参考:https://blog.csdn.net/qq_36552550/article/details/105835108

1.最近邻分类器原理

前面的CIFAR可视化将200副图像保存在了10个文件夹当中,观察ship文件夹中的前两幅图片“8.jpg”以及“62.jpg”,如图1所示。直观上来看,天空和大海都是蓝色的,船则是白色的,位于图像正中间;照此推理,相似的类别的图像,比如船,图像大致是类似的。

图5-3-1 ship文件夹中前两幅图像对比

那么,要判断test_batch中的某一幅图像属于哪一个类别,可以将该图像和data_batch1至data_batch5的图像依次比对,找出最相似的一副图像,这样就认为该图像和最相似图像属于一个类别。

具体实现上,将test_batch中的图像的每一个像素的RGB数值依次减去data_batch1至data_batch5的图像的每一个像素的RGB数值,将相减的数求绝对值,然后将所有的绝对值相加,得出和值,依照这个和值的大小来判断两幅图像的相似度;两幅图像相似程度越高,这个和值应该越低。以此,可以推断test_batch中图像属于哪一个类别。

该过程可以视作求取两向量L1距离的过程。因为每幅图像在CIFAR-10中以行向量进行保存,则可认为两幅图像为两个向量I1、I2,求两向量的L1距离即可得出结果:

(L1距离为求差值的绝对值,而L2距离则是求平方和的开平方;这里使用L1距离的好处就是计算量更小)

 Numpy的广播机制、sum()函数以及argmin()函数

test_batch文件同样是一行代表一副图片,然后将该行依次减去data_batch_1至5的每一行,如果将data_batch_1至5的图像数据全部拼接在一起,相当于是一个1*3072的数组减去一个50000*3072的数组的每一行。这里面就涉及两个编程实现的问题——1.data_batch_1至5的数据拼接;2.一个1*3072的数组减去一个50000*3072的数组的每一行的实现。

首先,看一下数据拼接的问题。将data_batch_1至5文件中字典dictionary类型里面的图像数据和标签读出,读出后为列表list类型,进行计算的时候需要提前将list类型转换成Numpy的array类型,并且维度也要符合50000*3072需要。

接下来看一个简单的程序例子,如程序1所示。

程序1 数据拼接示例

import numpy as np

x = []
a = [[1,2],[3,4]]
b = [[5,6],[7,8]]
print(a)
print(b)
x.append(a)
print(x)
x.append(b)
print(x)

xb = np.array(x)
print(xb)
print(xb.shape)

xa = np.concatenate(x)
print(xa)
print(xa.shape)

首先看第2行至第11行,通过append()函数,列表x依次将列表a和列表b放入自己的列表中;如图2所示。

图2 列表x续接结果示意图

这个时候如果直接转为Numpy的array类型,即13行至15行,那么得到的结果如图3所示,是一个2*2*2的数组。

图3 拼接后直接转数组array类型结果示意图

如果想拼接位一个4行2列的数组怎么办呢?这时候可以使用numpy中的concatenate()函数,具体该函数的用法可以自行查阅资料。程序1中将2*2*2的列表类型转换为了4*2的数组类型。

图4 拼接后

拼接问题解决后,就可以实现一个1*3072的数组减去一个50000*3072的数组的每一行,当然,这里写for语句循环也可以。但是Numpy提供更简单的方法——广播机制。一个示例如果程序2所示。

程序2 广播机制示例

import numpy as np

a = np.array([[1,2],[3,4],[5,6]])
b = np.array([1,1])
c = np.array([[1],[1]])

r1 = a - b
#r2 = a - c #error
r3 = b + c
r4 = b - a
#r5 = c - a  #error
print(r1)
print(r3)
print(r4)

分别创建数组a,b,c,其维度分别为3*2,1*2,2*1。

第7行a-b可以认为a加上一个负的b,可以看到a数据每一行都加上了一个负的b,如图5所示。

5 a-b结果示意图

同理,b-a可以认为b加上一个负的a,如图6所示。

图6 b-a结果示意图。

可以看到,广播机制可以自动补齐数组,以方便进行俩数组的加减。第9行1*2数组b和2*1数组c亦可以进行加减。但是,第8行以及第11行的无法通过填补实现广播机制。

 

完成两个数组的减法后,还需要对获得的每一行的数值进行求绝对值的和,并且在求和后的结果中找到最小的那个数。这需要用到两个求和函数sum()以及获取数组中最小数值的下标函数argmin(),如程序3所示。

程序3 sum()以及argmin()使用示例

import numpy as np

arr1 = np.array([[10,20],[-3,-4],[5,6],[0,1]])
arr2 = np.abs(arr1)
print(arr2)

arr_row_sum = np.sum(arr2,axis = 1)
print(arr_row_sum)
print(arr_row_sum.shape)

min_sum = np.argmin(arr_row_sum)
print(min_sum)

程序结果如图7所示。

图7 程序3结果示意图

创建4行3列数组arr1,对arr1求绝对值获得arr2,打印arr2;第7行调用sum()函数实现对arr2进行求和,其中第二个参数axis等于0时对列求和,等于1时对行求和;打印arr_row_sum可看到结果为[30 7 11 1],虽然是横向显示,但查看该数组的shape属性,可以看到是4行的数组,而非4列。最后调用argmin()函数获取arr_row_sum中的最小值的下标,可以看到结果返回了3,对应的数字1。

实现CIFAR-10图像分类

测试计算机装Window 10系统,4G内存,安装有常用软件;但一次性读取data_batch1至data_batch5时直接内存爆炸。

为了防止将五个训练集文件全部读取造成内存不足的情况出现,该小节程序只选择了data_batch1以及data_batch2作为训练集。

CIFAR-10图像分类实现如程序4所示。

程序4 基于最近邻分类器实现CIFAR-10图像分类

import pickle
import os
import numpy as np

n = 2

def unpickle_as_array(filename):
    with open(filename, 'rb') as f:
        dic = pickle.load(f,encoding='latin1')
        dic_data = dic['data']
        dic_labels = dic['labels']
        dic_data = np.array(dic_data).astype('int')   
        dic_labels = np.array(dic_labels).astype('int')  
        return dic_data, dic_labels

def load_batches(root,n):
    train_data = []
    train_labels = []
    for i in range(1,n+1,1):
        f = os.path.join(root,'data_batch_%d' %i)
        data, labels = unpickle_as_array(f)
        train_data.append(data)
        train_labels.append(labels)
    train_data_r = np.concatenate(train_data)   
    train_labels_r = np.concatenate(train_labels)
    del train_data, train_labels
    test_data, test_labels = unpickle_as_array(os.path.join(root, 'test_batch'))
    return train_data_r, train_labels_r, test_data, test_labels

def nn_classification(train_d, test_d, train_l):
    count = 0
    result = np.zeros(10000)   
    for i in range(10000):
        d_value = test_d[i] - train_d   
        distance = np.sum(np.abs(d_value), axis=1) 
        min_dis = np.argmin(distance)  
        result[i] = train_l[min_dis]
        print('the %dth image\'s label:  %d' % (count, result[i]))
        count = count + 1
    return result

train_data, train_labels, test_data, test_labels = load_batches('E:/cifar/cifar-10-batches-py', n)
result = nn_classification(train_data, test_data, train_labels)
print('the algorithm\'s accuracy: %f' % (np.mean(result == test_labels)))

第5行的n表示使用多少个训练集,如计算机内存较小,一次使用5个容易造成内存爆炸,在本程序中设置为2,如果想读取5个进行测试可将n赋值改为5即可;其次,训练集越大,需要计算的时间也越长。

(跑完以上程序的参考时间:Intel(R) Core(TM) i5-6200U CPU @ 2.3GHz 2.40GHz,64位系统,完成以上程序耗时大约70分钟)

16至28行代码实现了函数load_batches(),将n个训练集文件读入,root为文件的根路径,函数实现使用了append()以及concatenate()函数,前文已经讲过,这里不再累述。

30至40行 代码实现了最近邻分类器——nn_classification()函数,结果保存在一个10000行的result中, 因为测试集总共10000副图片,对应10000行,所以需要循环10000次得到所有结果,for循环语句内通过广播机制、求绝对值的和值、找到最小值下标等操作,得到result。

为了获取最近邻分类器的准确度,通过将测试集最终结果result测试集真实的标签之间进行比对,然后求其均值,得到最终的准确度。

以上程序输出结果如图8所示。

图8 基于最近邻分类器实现CIFAR-10图像分类结果截图

可以看出,最终的识别准确率虽然只达到了33.85%,但比随机猜测的10%要高出来很多。

2.k最近邻分类器

k最近邻分类器原理

当使用最近邻分类器进行test_batch中图像的预测时,只选取了最类似图像的标签。除此之外,还可以使用k最近邻分类器。有了最近邻分类器,这个k最近邻分类器就很简单了:最近邻分类器是在训练集中找到最接近的1图像,而k最近邻分类器则是找到最接近的K个图像,最接近的K个图像中最多的那个标签类别即分类结果。可知,当k=1时,K最近邻分类器即最近邻分类器。

 k最近邻分类的函数实现

这里只需要更改程序1中的NNClassTest()函数即可,新的KNNClassTest()函数如下2所示。

程序5 K最近邻分类器的函数实现

import pickle
import os
import numpy as np

n = 2

def unpickle_as_array(filename):
    with open(filename, 'rb') as f:
        dic = pickle.load(f,encoding='latin1')
        dic_data = dic['data']
        dic_labels = dic['labels']
        dic_data = np.array(dic_data).astype('int')   
        dic_labels = np.array(dic_labels).astype('int')  
        return dic_data, dic_labels

def load_batches(root,n):
    train_data = []
    train_labels = []
    for i in range(1,n+1,1):
        f = os.path.join(root,'data_batch_%d' %i)
        data, labels = unpickle_as_array(f)
        train_data.append(data)
        train_labels.append(labels)
    train_data_r = np.concatenate(train_data)   
    train_labels_r = np.concatenate(train_labels)
    del train_data, train_labels
    test_data, test_labels = unpickle_as_array(os.path.join(root, 'test_batch'))
    return train_data_r, train_labels_r, test_data, test_labels

def knn_classification(train_d, test_d, train_l, k):
    count = 0
    result = np.zeros(10000)
    for i in range(10000):
        d_value = test_d[i] - train_d
        distance = np.sum(np.abs(d_value), axis=1)
        dis_sort = np.argsort(distance)
        vote_label = np.zeros(10)
        for j in range(k):
            vote_label[train_l[dis_sort[j]]] += 1
        result[i] = np.argmax(vote_label)
        print('the %dth image\'s label:  %d' % (count, result[i]))
        count = count + 1
    return result

train_data, train_labels, test_data, test_labels = load_batches('E:/cifar/cifar-10-batches-py', n)
result = knn_classification(train_data, test_data, train_labels,3)
print('the algorithm\'s accuracy: %f' % (np.mean(result == test_labels)))

K最近邻分类器程序实现只需在程序4上进行部分修改即可。程序5 的30行以前代码和4一致,这里不再在书中显示。

程序5在30行开始实现了knn_classification()函数,多了一个参数k,因为这里需要找到差值绝对值之和最小的k个图像。

那么,首先要对所求的差值进行排序,在36行代码中使用argsort()函数——返回数组值从小到大的索引值。

创建vote_label 数组,对差值绝对值之和最小的k个图像对应的标签进行记录。

第37至40行是关键——假定k=3,那么for循环循环3次,j分别为0,1,2;那么dis_sort[0]dis_sort[1]dis_sort[2]分别表示前3个最小的差值绝对值之和图像的索引,有了图像索引,就可以通过索引去找到该图像对应的标签,即train_l[dis_sort[j]]获得了对应的标签,那么就可以在该标签投一票;假如train_l[dis_sort[0]],train_l[dis_sort[1]],train_l[dis_sort[2]]分别为3,6,3(也就是对应标签为3,6,3);那么标签3就有了两票,而6有了一票;其他标签0票,即 在for循环中,vote_label[train_l[dis_sort[j]]] 要加一,表示对应标签上面投一票,3次循环结束,vote_label应为[0,0,0,2,0,0,1,0,0,0];可以看出vote_label中最大的值为2,再通过argmax()函数获取数组中最大值对应的下标,这里应该为3了,那么结果即为3。

47行调用knn_classification()函数,其中第四个参数k值为3,程序运行结果如图9所示。

图9 基于k最近邻分类器实现CIFAR-10图像分类结果截图

在某些场景下k-NN算法的效果要好于NN算法,但可以看出在本例中其准确度为0.3333,低于NN算法的准确度。

可以看到以上方法有着一些明显的缺点: 最近邻分类的过程是通过比对所有数据集中训练集的图片来完成的,所以必须将所有图片读取在内存中,容易造成内存爆炸;其次,对一幅图像进行判断类别,需要比对所有训练集的图像,识别的过程消耗计算量巨大;最重要的是,该方法的识别正确率也差强人意,对于CIFAR-10数据集只有30%左右。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手教你K最近邻分类器分类CIFAR-10 的相关文章

  • 机器学习基础-模型调参

    模型调参 大多数据科学家或算法工程师会在模型调参上面花费很多时间 时间的花费和你模型的参数成正比关系 所以 我们的模型想在一个数据集上获得一个好的结果是一个非常花费时间的过程 一般来讲 大家在模型调参之初 都会有官方模型设定的一系列默认超参
  • XGBoost详解

    文章目录 背景 目标函数 最优切分点算法 Shrinkage 收缩过程 缺失值处理 优缺点 总结 背景 在看Xgboost之前 先看看笔者写的AdaBoost 和GBDT AdaBoost 关注的是哪些错误分类的样本 每次加大误分类样本的权
  • LightGBM 相关知识理解

    文章目录 lightGBM 简介 直方图算法 Histogram algorithm 基本思想 直方图做差 带深度限制的 Leaf wise 算法 单边梯度采样算法 GOSS 互斥特征捆绑算法 EFB 1 解决哪些特征应该绑在一起 2 解决
  • LightGBM 重要参数、方法、函数理解及调参思路、网格搜索(附例子)

    文章目录 一 LightGBM 原生接口 重要参数 训练参数 预测方法 绘制特征重要性 分类例子 回归例子 二 LightGBM 的 sklearn 风格接口 LGBMClassifier 基本使用 例子 LGBMRegressor 基本使
  • sklearn 中的线性回归、岭回归、Lasso回归参数配置及示例

    文章目录 线性回归 引入 重要参数 重要属性 重要方法 例子 岭回归 引入 重要参数 重要属性 重要方法 示例 Lasso 回归 引入 重要参数 重要属性 重要方法 示例 本文主要讲一些sklearn中回归模型的使用 如果需要了解相关理论
  • Sigmoid激活函数和ReLU激活函数的区别:

    Sigmoid激活函数和ReLU激活函数的区别 特性 Sigmoid 激活函数 ReLU 激活函数 梯度弥散 只有在0附近的时候有比较好的激活性 在正负饱和区 其梯度都接近于0 导致梯度弥散 在大于0的部分梯度为常数 不会出现梯度弥散 单侧
  • 机器学习(一)

    一 数据结构的组成 数据结构大部分为 特征值 目标值 但是也有些数据没有目标值 在机器学习中常常使用pandas来进行数据的处理以及基本格式的调节 一 特征值 一般情况下 能反映出目标所存在的特征的数值为特征值 例如 我们要判断一个人的性别
  • 训练集(离线)与测试集(上线)效果差距很大怎么办?

    前言 相信各位童鞋在跑模型的时候时不时会遇到一个尴尬的现象 就是你在训练集或者验证集的模型效果好到令人发指 一时间以为 哼 就这 游戏结束 结果当你在测试集或者上线后发现真的就游戏结束了 指标低的没眼看 本人还是一个算法菜鸟时就遇到过这种情
  • 机器学习(五)

    一 数据降维 一 特征选择 特征选择是去除一些与预测结果没有关系或者两个特征有高度关联的特征作为机器学习接下来训练集 这里举个例子 预测狗的品种 这里有毛的颜色 有没有牙齿 眼睛颜色 显然有没有牙齿这一特征与预测结果没有关系 这里则需要将这
  • AB test 之 广告投放(二)

    在广告投放的A B测试中 有几个重要的注意要点需要考虑 目标和假设 明确测试的目标 并基于此制定假设 确定您希望测试的指标 例如点击率 转化率 收入等 并提出假设 即测试组和对照组之间是否存在显著差异 随机分组 确保测试组和对照组的分配是随
  • 多标签学习之白话版

    简单的机器学习 就是把人类的学习方式教给机器 斯 cdot 沃索迪 1 任务的提出 单标签学习 假设你不知道河豚长什么样子 给你 1000 张照片 并标注哪些有河豚 再给你 100 张新的照片 你能判断哪些照片里面有河豚吗 本例中 从 10
  • ELI5:导数,偏导数

    导数 导数就是描述某个事物的变化速率 举个最常见的例子 当人从某地移动到另一地点的时候 速度就是这个移动的导数 因为它描述了移动的变化速率 再继续看 加速度就是速度的导数 因为加速度描述了速度的变化速率 当加速度恒定的时候 我们可以想到 速
  • 机器学习基础(六)——逻辑回归Logistic Regression

    文章目录 Logistic Regression 1 基础概念 1 1 对数似然损失函数 1 2 完整的损失函数 2 逻辑回归算法API 3 LogisticRegression回归案例 Logistic Regression 1 基础概念
  • 机器学习数学基础(一):机器学习与数学分析

    机器学习数学基础 一 机器学习 概念 什么是机器学习 什么是学习 内涵与外延 流程 重点知识 Code 机器学习与数学分析 极限 导数 幂指函数 离散加和 连续积分 泰勒公式 应用 方向导数 梯度 特殊函数 函数 凸函数 一阶可微 二阶可微
  • 机器学习基础篇-数据清洗

    Capture 1 在机器学习的工作流中 数据清洗环节尤为重要 接下来首先让我们看一下数据预处理的流程图 总的来说 主要包含下面三大块 收集数据 标注数据 提升数据质量 Capture 2 NO 1 Data Errors 所谓数据错误 就
  • 过拟合产生的原因和解决方案

    最近在研究室内定位的问题 总是过拟合 之前研究问题太过草率 这次计划将问题彻底的研究明白 过拟合 简单来说就是在训练集表现好 在测试集 验证集 表现差 从表现来看可以理解成模型复杂也好 还是你的数据有问题也好 总之最后模型学习到了你现在数据
  • 拉普拉斯近似算法小结

    序 在机器学习中 经常遇到需要对复杂分布进行近似的情况 目前常用的近似算法主要有三种 拉普拉斯近似 变分近似 Gibbs采样 其中拉普拉斯近似算法是用一个高斯分布来近似原始分布 当原始分布比较简单的时候效果会较好 目标 用一个高斯分布近似一
  • 手把手教你CIFAR数据集可视化

    CIFAR数据集介绍与获取 如同从小到的父母教我们识别每个物体是什么一样 除了看到的画面 父母会在旁边告诉看到的画面是什么 这种学习方式叫做监督学习 与此对应还有无监督学习 计算机也一样 数据集通常应该至少包含两部分内容 一个是图像 一个是
  • 决策树和随机森林的实现,可视化和优化方法

    决策树原理 决策树原理这篇文章讲的很详细 本文仅写代码实现 构造决策树 matplotlib inline import matplotlib pyplot as plt import pandas as pd from sklearn d
  • 手把手教你K最近邻分类器分类CIFAR-10

    KNN算法全称为k Nearest Neighbor Classifier 即k最近邻分类器 它可以看作是Nearest Neighbor Classifier最近邻分类器的加强版 无论是最近邻分类器还是k最近邻分类器 其原理都比较简单 其

随机推荐

  • jqGrid 编辑完数据后能返回到当前位置的方法

    jqGrid 是一个js的jquery组件 虽然不轻便 但功能还是蛮强大的 也比较方便使用 在数据加载后 经常需要对其中的记录进行编辑 修改完后再返回时需要看到修改后的数据 一般采取重新加载的方法reloadGrid 但问题是列表中的数据因
  • STM8自学入门方向

    我还是我 今年计划自学学习STM8和汇编基础 STM8花了半个月 学的一点皮毛 对芯片有一定的了解了 学完后 发现可以拿到的资源远远没有32多 学习了内部大部分常用资源的应用 IO操作 定时器 IO中断 RS232 IIC 后面会发布我的总
  • 大数据时代下的个人知识管理

    前言 说到个人知识管理 在之前通过网络查询了一些资料 定义看起来让人蠢蠢欲动 作用是能快速找到自己收藏的文档 每个人或多或少都必须的有一些文件管理的习惯 管理就是一种习惯 利用专业的软件可以更容易的养成个人知识管理的习惯 当不小心清空了自己
  • c++双向列表释放_Python 列表List常见操作和错误总结

    一 列表的输入 即从控制台读取输入 然后创建列表 1 一维列表创建常见的方法有 当然 可以进一步简化成下面这样 其中第二句 在列表里用到了列表解析式 这是非常Pythonic的写法 酷炫 2 二维列表的输入和创建 二维列表复杂一些 可以以矩
  • Quartz-Spring[一]之MethodInvokingJobDetailFactoryBean配置任务

    Spring中使用Quartz的3种方法 MethodInvokingJobDetailFactoryBean implements Job extends QuartzJobBean 动态启动 暂定 添加 删除定时功能 可传参数 Quar
  • React之state、hooks性能分析

    目录 一 state 1 为什么使用setState 2 setState异步更新 3 如何获取异步的结果 4 setState一定是异步吗 5 源码分析 6 数据的合并 7 多个state的合并 二 为什么需要Hook 三 Class组件
  • stm32之iap实现应用(基于串口,上位机,详细源码)

    开发环境 Window 7 开发工具 Keil uVision4 硬件 stm32f103c8t6 篇幅略长 前面文字很多 主要是希望能让小白们理解 后面就是实现步骤 包括实现的代码 在研发调试的时候我们一般用烧录器下载代码 对于stm32
  • 4.0创建型模式 描述

    创建型模式的主要关注点是 怎样创建对象 它的主要特点是 将对象的创建与使用分离 这样可以降低系统的耦合度 使用者不需要关注对象的创建细节 对象的创建由相关的工厂来完成 就像我们去商场购买商品时 不需要知道商品是怎么生产出来一样 因为它们由专
  • mysql按照某个字段值内容排序

    举个栗子 假如一个商品下 有多个货品 各个货品的状态值都不一样 那么当只想展示商品中的某一个货品时 希望用户端看到的优先级是在售的货品中的一个 根据mysql提供的方法 field column value1 value2 value3 可
  • RTThread学习有关的Keil的两个符号 $Sub$ $main 与 $Super$ $main

    Keil的两个符号 Sub 与 Super 是其做的打 补丁 功能 具体调用方法就是程序中包含有main函数 和 Sub main Super main 两个符号 源码先放出来 re define main function int Sub
  • 三校生计算机教育,三校生有什么专业

    三校生的专业有计算机信息类 旅游类 艺术类 电工技术类 农林类 机械类 建筑工程类 经济管理类 外语类 烹饪 生物化学类 国土资源类 体育类 教育类 交通运输类 自动化类 包装印刷类 医学类 护理学 药学类 铁道运输类 师范类 水利水电类
  • CTreeView

    ClassWizard为CTreeCtrl 树控件 添加的NM DBLCLK 双击 消息的响应函数中带有一个NMHDR 型指针形参 1 OnDblClkTree NMHDR pNMHDR LRESULT pResult 这个陌生的指针类型常
  • IDEA中使用Java连接MySQL数据库的配置和使用方法

    文章目录 IDE和必要配置 数据库连接代码 IDE和必要配置 IDE IntelliJ IDEA 2023 1 必要配置 1 安装好JDK 并且配置环境变量 2 导入MYSQL数据库所需的驱动 如果没有导入 可以参考这篇文章IDEA中的My
  • android Scroller

    参考 http www linuxidc com Linux 2016 01 127276 htm 以前只知道怎么使用scroller 照猫画虎 复制粘贴 今天遇到使用scroller 还是要去搜索 这样不行 要搞懂原理 上面的博客写的很漂
  • 静态链表

    include
  • Linux下防御ddos攻击

    1 Linux下防御ddos攻击 导读 Linux服务器在运营过程中可能会受到黑客攻击 常见的攻击方式有SYN DDOS等 通过更换IP 查找被攻击的站点可能避开攻击 但是中断服务的时间比较长 比较彻底的解决方法是添置硬件防火墙 不过 硬件
  • spring-boot的快速开发

    1 使用Intellij中的Spring Initializr来快速构建Spring Boot Cloud工程 菜单栏中选中Files gt New gt Projects 这个Initializr Service URL 我们一般使用默认
  • 短视频文案如何写,学会以下几种方法,离爆款绝对不远。

    短视频运营 视频肯定是关键 文案是对视频的一种衬托 但是也并不代表文案不重要 在短视频中的段子文案也是精心设计的 所以今天要分享的是视频介绍里的文案 是怎么炼成的 下面就跟大家讲讲如何写出比较好的视频文案 仅仅是形式 具体还是要看自己进行灵
  • 如何在figma中做交互设计

    近一年来 Figma它可以说是体验设计领域最受欢迎的工具 最近 我开始频繁地工作 Axure9 0和Figma切换使用 深刻感受到设计细节带来的体验差异化 今天 通过一些细节和亮点 总结了工具软件体验设计的几个原则 添加图片注释 不超过 1
  • 手把手教你K最近邻分类器分类CIFAR-10

    KNN算法全称为k Nearest Neighbor Classifier 即k最近邻分类器 它可以看作是Nearest Neighbor Classifier最近邻分类器的加强版 无论是最近邻分类器还是k最近邻分类器 其原理都比较简单 其