第六章 支持向量机

文章目录

  • 支持向量机
    • 间隔和支持向量
    • 对偶问题
      • 问题推导
      • SMO
    • 核函数
    • 实验

支持向量机

⽀持向量机(Support Vector Machines,SVM)

  • 优点:泛化错误率低,计算开销不⼤,结果易解释。
  • 缺点:对参数调节和核函数的选择敏感,原始分类器不加修改仅适⽤于处理⼆类问题。
    适⽤数据类型:数值型和标称型数据。

间隔和支持向量

假设数据是可分的,该算法就是为了找到一个超平面将两者分开
⽀持向量(support vector)就是离分隔超平⾯最近的那些点。接下来要试着最⼤化⽀持向量到分隔⾯的距离,需要找到此问题的优化求解⽅法

分割超平面的方程为 w T x + b = 0 w^Tx+b=0 wTx+b=0
计算点A到分割超平面的距离 r = ∣ w T x + b ∣ ∣ ∣ w ∣ ∣ r=\cfrac{|w^Tx+b|}{||w||} r=∣∣w∣∣wTx+b

为了方便计算,类别标签label使用+1和-1: l a b e l ∗ w T x + b \mathrm{label}*w^Tx+b labelwTx+b可以同号。
现在的目标就是找出分类器定义中的w和b。为此要找到具有最小间隔的数据点,而这些数据点也就是前面提到的支持向量对该间隔最大化 arg ⁡ max ⁡ w , b { min ⁡ n ( l a b e l ⋅ ( w T x + b ) ) ⋅ 1 ∥ w ∥ } \arg\max_{w,b}\left\{\min_n(\mathrm{label}\cdot(w^\mathrm{T}x+b))\cdot\frac1{\|w\|}\right\} argw,bmax{nmin(label(wTx+b))w1}

为了简化问题,令支持向量到超平面距离为1: r ≥ 1 r\geq 1 r1 ,则有 { w T x i + b ⩾ + 1 , y i = + 1 w T x i + b ⩽ − 1 , y i = − 1 \left\{\begin{array}{ll}\boldsymbol{w^\mathrm{T}}\boldsymbol{x_i}+b\geqslant+1,&y_i=+1\\\boldsymbol{w^\mathrm{T}}\boldsymbol{x_i}+b\leqslant-1,&y_i=-1\end{array}\right. {wTxi+b+1,wTxi+b1,yi=+1yi=1

两个一类支持向量到超平面的距离之和为 γ = 2 ∣ ∣ w ∣ ∣ \gamma=\frac2{||\boldsymbol{w}||} γ=∣∣w∣∣2

要使得间隔最大 max ⁡ 2 ∣ ∣ w ∣ ∣ \max\frac2{||w||} max∣∣w∣∣2,等价于 min ⁡ 1 2 ∣ ∣ w ∣ ∣ 2 \min\frac12||w||^2 min21∣∣w2,即 min ⁡ 1 2 ∣ ∣ w ∣ ∣ 2 s . t . y i ( w T x i + b ) ≥ 1 \min\frac{1}{2}||w||^2\quad s.t.\quad y_i(w^Tx_i+b)\geq 1 min21∣∣w2s.t.yi(wTxi+b)1

对偶问题

问题推导

回顾一下高等数学中约束极值的求法:
z = f ( x , y ) z=f(x,y) z=f(x,y)在条件 ψ ( x , y ) = 0 \psi(x,y)=0 ψ(x,y)=0下取得极值,求极值:

  1. 构造拉格朗日函数 F ( x , y , λ ) = f ( x , y ) + λ ψ ( x , y ) F(x,y,\lambda)=f(x,y)+\lambda\psi(x,y) F(x,y,λ)=f(x,y)+λψ(x,y)
  2. { f x ′ ( x , y ) + λ ψ x ′ ( x , y ) = 0 f y ′ ( x , y ) + λ ψ y ′ ( x , y ) = 0 ψ ( x , y ) = 0 \left\{\begin{aligned} &f'_x(x,y)+\lambda\psi'_x(x,y)=0\\ &f'_y(x,y)+\lambda\psi'_y(x,y)=0\\ &\psi(x,y)=0\\ \end{aligned}\right. fx(x,y)+λψx(x,y)=0fy(x,y)+λψy(x,y)=0ψ(x,y)=0
  3. 将求出的点带入

现问题:求 1 2 ∣ ∣ w ∣ ∣ 2 \frac12||w||^2 21∣∣w2 y i ( w T x i + b ) ≥ 1 y_i(w^Tx_i+b)\geq 1 yi(wTxi+b)1条件下的最小值

解决方法:引入拉格朗日乘子 α i ⩾ 0 \alpha_{i}\geqslant0 αi0,构造拉格朗日函数 L ( w , b , α ) = 1 2 ∥ w ∥ 2 + ∑ i = 1 m α i ( 1 − y i ( w T x i + b ) ) L(\boldsymbol{w},b,\boldsymbol{\alpha})=\frac12\left.\|\boldsymbol{w}\|^2+\sum_{i=1}^m\alpha_i\left(1-y_i(\boldsymbol{w}^\mathrm{T}\boldsymbol{x}_i+b)\right)\right. L(w,b,α)=21w2+i=1mαi(1yi(wTxi+b))

其中 α = ( α 1 ; α 2 ; … ; α m ) \boldsymbol{\alpha}=(\alpha_{1};\alpha_{2};\ldots;\alpha_{m}) α=(α1;α2;;αm) ,对w和b偏导为0可得: w = ∑ i = 1 m α i y i x i , 0 = ∑ i = 1 m α i y i . \begin{aligned}\boldsymbol{w}&=\sum_{i=1}^m\alpha_iy_i\boldsymbol{x}_i,\\0&=\sum_{i=1}^m\alpha_iy_i.\end{aligned} w0=i=1mαiyixi,=i=1mαiyi.

联立后,可解得对偶问题 max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j x i T x j s . t . ∑ i = 1 m α i y i = 0 , α i ⩾ 0 , i = 1 , 2 , … , m . \max_{\boldsymbol{\alpha}}\sum_{i=1}^m\alpha_i-\frac12\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_j\boldsymbol{x}_i^\mathrm{T}\boldsymbol{x}_j\\ \begin{aligned}\mathrm{s.t.}\quad&\sum_{i=1}^m\alpha_iy_i=0, \\ &\alpha_i\geqslant0,\quad i=1,2,\ldots,m. \end{aligned} αmaxi=1mαi21i=1mj=1mαiαjyiyjxiTxjs.t.i=1mαiyi=0,αi0,i=1,2,,m.

最后模型为 f ( x ) = w T x + b = ∑ i = 1 m α i y i x i T x + b . s . t . { α i ⩾ 0 ; y i f ( x i ) − 1 ⩾ 0 ; α i ( y i f ( x i ) − 1 ) = 0. \begin{aligned}f(\boldsymbol{x})&=\boldsymbol{w}^\mathrm{T}\boldsymbol{x}+b\\&=\sum_{i=1}^m\alpha_iy_i\boldsymbol{x}_i^\mathrm{T}\boldsymbol{x}+b.\end{aligned} \\\mathrm{s.t.}\left\{\begin{array}{l}\alpha_i\geqslant0;\\y_if(\boldsymbol{x}_i)-1\geqslant0;\\\alpha_i\left(y_if(\boldsymbol{x}_i)-1\right)=0.\end{array}\right. f(x)=wTx+b=i=1mαiyixiTx+b.s.t. αi0;yif(xi)10;αi(yif(xi)1)=0.

SMO

推导的式子已经得到了,但是如何求解这些参数?SMO是其中一个高效算法的代表。
SMO的基本思路是先固定 α i \alpha_i αi之外的所有参数,然后求 α i \alpha_i αi上的极值.由于存在约束 ∑ i = 1 m α i y i = 0 \sum_{i=1}^m\alpha_iy_i=0 i=1mαiyi=0,若固定 α i \alpha_i αi之外的其他变量,则 α i \alpha_i αi可由其他变量导出.于是,SMO每次选择两个变量 α i \alpha_i αi α j \alpha_j αj,并固定其他参数.这样,在参数初始化后,SMO不断执行如下两个步骤直至收敛:

  • 选取一对需更新的变量 α i \alpha_i αi α j \alpha_j αj;
  • 固定 α i \alpha_i αi α j \alpha_j αj以外的参数,求解式获得更新后的 α i \alpha_i αi α j \alpha_j αj.

则约束变为 α i y i + α j y j = c , α i ⩾ 0 , α j ⩾ 0 c = − ∑ k ≠ i , j α k y k \begin{aligned}\alpha_iy_i+\alpha_jy_j&=c,\alpha_i\geqslant0,\alpha_j\geqslant0\\\\c&=-\sum_{k\neq i,j}\alpha_ky_k\end{aligned} αiyi+αjyjc=c,αi0,αj0=k=i,jαkyk

确定偏移项b的时候,现实任务中常采用一种更鲁棒的做法:使用所有支持向量求解的平均值(支持向量下标集 S = { i ∣ α i > 0 , i = 1 , 2 , … , m } S=\{i\mid\alpha_{i}>0,i=1,2,\ldots,m\} S={iαi>0,i=1,2,,m}): b = 1 ∣ S ∣ ∑ s ∈ S ( y s − ∑ i ∈ S α i y i x i T x s ) b=\frac{1}{|S|}\sum_{s\in S}\left(y_s-\sum_{i\in S}\alpha_iy_i\boldsymbol{x}_i^\mathrm{T}\boldsymbol{x}_s\right) b=S1sS(ysiSαiyixiTxs)

核函数

有时数据并不是线性可分,为解决此问题,可将样本从原始空间映射到一个更高维的特征空间,使得样本在这个特征空间线性可分。

ϕ ( x ) \phi(\boldsymbol{x}) ϕ(x)表示将 x \boldsymbol{x} x映射后的特征向量: f ( x ) = w T ϕ ( x ) + b f(x)=\boldsymbol{w}^\mathrm{T}\phi(\boldsymbol{x})+b f(x)=wTϕ(x)+b

对偶问题是 max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j ϕ ( x i ) T ϕ ( x j ) s . t . ∑ i = 1 m α i y i = 0 , α i ⩾ 0 , i = 1 , 2 , … , m . \max_{\boldsymbol{\alpha}}\sum_{i=1}^m\alpha_i-\frac12\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_j\phi(\boldsymbol{x}_i)^\mathrm{T}\phi(\boldsymbol{x}_j)\\ \begin{aligned}\mathrm{s.t.}\quad&\sum_{i=1}^m\alpha_iy_i=0, \\ &\alpha_i\geqslant0,\quad i=1,2,\ldots,m. \end{aligned} αmaxi=1mαi21i=1mj=1mαiαjyiyjϕ(xi)Tϕ(xj)s.t.i=1mαiyi=0,αi0,i=1,2,,m.

为了简化 ϕ ( x i ) T ϕ ( x j ) \phi(\boldsymbol{x}_i)^\mathrm{T}\phi(\boldsymbol{x}_j) ϕ(xi)Tϕ(xj),设想一个函数: κ ( x i , x j ) = ⟨ ϕ ( x i ) , ϕ ( x j ) ⟩ = ϕ ( x i ) T ϕ ( x j ) \kappa(\boldsymbol{x}_i,\boldsymbol{x}_j)=\langle\phi(\boldsymbol{x}_i),\phi(\boldsymbol{x}_j)\rangle=\phi(\boldsymbol{x}_i)^\mathrm{T}\phi(\boldsymbol{x}_j) κ(xi,xj)=ϕ(xi),ϕ(xj)⟩=ϕ(xi)Tϕ(xj)

对偶问题重写为: max ⁡ α ∑ i = 1 m α i − 1 2 ∑ i = 1 m ∑ j = 1 m α i α j y i y j κ ( x i , x j ) s . t . ∑ i = 1 m α i y i = 0 , α i ⩾ 0 , i = 1 , 2 , … , m . \max_{\boldsymbol{\alpha}}\sum_{i=1}^m\alpha_i-\frac12\sum_{i=1}^m\sum_{j=1}^m\alpha_i\alpha_jy_iy_j\kappa(\boldsymbol{x}_i,\boldsymbol{x}_j)\\ \begin{aligned}\mathrm{s.t.}\quad&\sum_{i=1}^m\alpha_iy_i=0, \\ &\alpha_i\geqslant0,\quad i=1,2,\ldots,m. \end{aligned} αmaxi=1mαi21i=1mj=1mαiαjyiyjκ(xi,xj)s.t.i=1mαiyi=0,αi0,i=1,2,,m.

模型为: f ( x ) = w T ϕ ( x ) + b = ∑ i = 1 m α i y i ϕ ( x i ) T ϕ ( x ) + b = ∑ i = 1 m α i y i κ ( x , x i ) + b   . \begin{aligned} f(\boldsymbol{x})& =\boldsymbol{w^\mathrm{T}}\phi(\boldsymbol{x})+b \\ &=\sum_{i=1}^m\alpha_iy_i\phi(\boldsymbol{x}_i)^\mathrm{T}\phi(\boldsymbol{x})+b \\ &=\sum_{i=1}^m\alpha_iy_i\kappa(\boldsymbol{x},\boldsymbol{x}_i)+b\mathrm{~.} \end{aligned} f(x)=wTϕ(x)+b=i=1mαiyiϕ(xi)Tϕ(x)+b=i=1mαiyiκ(x,xi)+b .

κ ( ∗ , ∗ ) \kappa(*,*) κ(,) 就是核函数。常用核函数如下。
在这里插入图片描述

实验

导入数据

from numpy import *
from time import sleep
import random
def loadDataSet(fileName):
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        dataMat.append([float(lineArr[0]), float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat,labelMat
def selectJrand(i,m):
    j=i #we want to select any J not equal to i
    while (j==i):
        j = int(random.uniform(0,m))
    return j

def clipAlpha(aj,H,L):
    if aj > H: 
        aj = H
    if L > aj:
        aj = L
    return aj
dataMat,classLabels=loadDataSet('06testSet.txt')

进行数据可视化。

import matplotlib.pyplot as plt
import numpy as np
x = [row[0] for row in dataMat]
y = [row[1] for row in dataMat]
plt.scatter(x, y, c=['blue' if row == 1 else 'red' for row in classLabels])
plt.xlabel('X')
plt.ylabel('Y')

plt.show()

在这里插入图片描述

上图可以看出,数据是合法的:可以有一条直线(这条直线就是所需求的超平面)进行划分

实现SMO函数:

创建⼀个alpha向量并将其初始化为0向量
当迭代次数⼩于最⼤迭代次数时(外循环):
    对数据集中的每个数据向量(内循环):
        如果该数据向量可以被优化:
            随机选择另外⼀个数据向量
            同时优化这两个向量
        如果两个向量都不能被优化,退出内循环
    如果所有向量都没被优化,增加迭代数⽬,继续下⼀次循环
  Cell In[10], line 1
    创建⼀个alpha向量并将其初始化为0向量
                        ^
SyntaxError: invalid character in identifier
def smoSimple(dataMatIn, classLabels, C, toler, maxIter=50):
    dataMatrix = mat(dataMatIn)
    labelMat = mat(classLabels).transpose()
    b = 0
    m, n = shape(dataMatrix)
    alphas = mat(zeros((m, 1)))
    iter = 0
    while (iter < maxIter):
        alphaPairsChanged = 0
        for i in range(m):
            fXi = float(multiply(alphas, labelMat).T * (dataMatrix * dataMatrix[i, :].T)) + b
            Ei = fXi - float(labelMat[i])  # if checks if an example violates KKT conditions
            if ((labelMat[i] * Ei < -toler) and (alphas[i] < C)) or ((labelMat[i] * Ei > toler) and (alphas[i] > 0)):
                j = selectJrand(i, m)
                fXj = float(multiply(alphas, labelMat).T * (dataMatrix * dataMatrix[j, :].T)) + b
                Ej = fXj - float(labelMat[j])
                alphaIold = alphas[i].copy()
                alphaJold = alphas[j].copy()
                if (labelMat[i] != labelMat[j]):
                    L = max(0, alphas[j] - alphas[i])
                    H = min(C, C + alphas[j] - alphas[i])
                else:
                    L = max(0, alphas[j] + alphas[i] - C)
                    H = min(C, alphas[j] + alphas[i])
                if L == H:
                    # print("L==H")
                    continue
                eta = 2.0 * dataMatrix[i, :] * dataMatrix[j, :].T - dataMatrix[i, :] * dataMatrix[i, :].T - dataMatrix[
                     j,:] * dataMatrix[j,:].T
                if eta >= 0:
                    # print("eta>=0")
                    continue
                alphas[j] -= labelMat[j] * (Ei - Ej) / eta
                alphas[j] = clipAlpha(alphas[j], H, L)
                if (abs(alphas[j] - alphaJold) < 0.00001):
                    # print("j not moving enough")
                    continue
                alphas[i] += labelMat[j] * labelMat[i] * (alphaJold - alphas[j])
                b1 = b - Ei - labelMat[i] * (alphas[i] - alphaIold) * dataMatrix[i, :] * dataMatrix[i, :].T - labelMat[
                    j] * (alphas[j] - alphaJold) * dataMatrix[i, :] * dataMatrix[j, :].T
                b2 = b - Ej - labelMat[i] * (alphas[i] - alphaIold) * dataMatrix[i, :] * dataMatrix[j, :].T - labelMat[
                    j] * (alphas[j] - alphaJold) * dataMatrix[j, :] * dataMatrix[j, :].T
                if (0 < alphas[i]) and (C > alphas[i]):
                    b = b1
                elif (0 < alphas[j]) and (C > alphas[j]):
                    b = b2
                else:
                    b = (b1 + b2) / 2.0
                alphaPairsChanged += 1
                print("iter: %d i:%d, pairs changed %d" % (iter, i, alphaPairsChanged))
        if (alphaPairsChanged == 0):
            iter += 1
        else:
            iter = 0
        print("iteration number: %d" % iter)
    return b, alphas


b, alphas = smoSimple(dataMat, classLabels, 0.6, 0.001, maxIter=50)
b=b[0,0]

部分运行结果:

iter: 0 i:1, pairs changed 1
iter: 0 i:3, pairs changed 2
iter: 0 i:4, pairs changed 3
iter: 0 i:8, pairs changed 4
iter: 0 i:10, pairs changed 5
iter: 0 i:14, pairs changed 6
iter: 0 i:29, pairs changed 7
iter: 0 i:55, pairs changed 8
iteration number: 0
iter: 0 i:1, pairs changed 1
iter: 0 i:24, pairs changed 2
iter: 0 i:27, pairs changed 3
iter: 0 i:29, pairs changed 4
iter: 0 i:55, pairs changed 5
iter: 0 i:76, pairs changed 6
iteration number: 0
iter: 0 i:8, pairs changed 1
iter: 0 i:55, pairs changed 2
iter: 0 i:84, pairs changed 3
iteration number: 0
iter: 0 i:4, pairs changed 1
iter: 0 i:11, pairs changed 2
iter: 0 i:46, pairs changed 3
iter: 0 i:52, pairs changed 4
iter: 0 i:54, pairs changed 5
iteration number: 0
iter: 0 i:1, pairs changed 1
iter: 0 i:22, pairs changed 2
iter: 0 i:24, pairs changed 3
iter: 0 i:30, pairs changed 4
iteration number: 0
iter: 0 i:10, pairs changed 1
iteration number: 0
iter: 0 i:18, pairs changed 1
...
iteration number: 38
iteration number: 39
iteration number: 40
iteration number: 41
iteration number: 42
iteration number: 43
iteration number: 44
iteration number: 45
iteration number: 46
iteration number: 47
iteration number: 48
iteration number: 49
iteration number: 50

输出b和alphas

print(b)
print(alphas)

部分运行结果:

-3.7617698556024015
[[0.        ]
	...
 [0.        ]
 [0.12836263]
 [0.        ]
 [0.        ]
 [0.        ]
	 ...
 [0.        ]
 [0.23620881]
 [0.        ]
	...
 [0.        ]]

计算超平面向量 w = ∑ i = 1 m α i y i x i \boldsymbol{w}=\sum_{i=1}^m\alpha_iy_i\boldsymbol{x}_i w=i=1mαiyixi

def GetW(alphas,classLabels,dataMat):
    w=np.zeros(2)
    sv=[]
    for i in range(len(dataMat)):
        if alphas[i,0]>0:
            sv.append(i)
            w+= alphas[i,0]*classLabels[i]*np.array(dataMat[i])
    return sv,w
sv,w= GetW(alphas,classLabels,dataMat)
print(sv)
print(w)
[17, 29, 55]
[ 0.80226906 -0.27808456]

w 0 x + w 1 y + b = 0 w_0x+w_1y+b=0 w0x+w1y+b=0 可得 y = − w 0 x − b w 1 y=\cfrac{-w_0x-b}{w_1} y=w1w0xb

x = [row[0] for row in dataMat]
y = [row[1] for row in dataMat]
color=['blue' if classLabel == 1 else 'red' for classLabel in classLabels]
for i in sv:
    color[i]='black'
plt.scatter(x, y, c=color)
plt.xlabel('X')
plt.ylabel('Y')

x = np.linspace(min(x), max(x), 100)
y =(-w[0]*x-b)/w[1]

plt.plot(x, y)

plt.show()

在这里插入图片描述

如上图所示,将支持向量标记为黑点,其余平面两边的点分别标记为红点和蓝点。
通过该支持向量机算法,我们可以求得支持向量、求得超平面方程,将数据进行划分。⽀持向量机的泛化错误率较低,也就是说它具有良好的学习能⼒,且学到的结果具有很好的推⼴性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/53783.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 教程之标准库概览

概要 Python 标准库非常庞大&#xff0c;所提供的组件涉及范围十分广泛&#xff0c;使用标准库我们可以让您轻松地完成各种任务。 以下是一些 Python3 标准库中的模块&#xff1a; 「os 模块」 os 模块提供了许多与操作系统交互的函数&#xff0c;例如创建、移动和删除文件和…

CLIP-GCD: Simple Language Guided Generalized Category Discovery(论文翻译)

CLIP-GCD: Simple Language Guided Generalized Category Discovery 摘要1 介绍2 相关工作2.1 NCD2.2 无监督聚类2.3 自监督和多模态预训练 3 方法3.1 GCD 问题设置3.2 我们的方法3.2.1 使用CLIP 在GCD 4 实验4.1 模型架构细节4.2 数据集和评估4.3 和最先进水平比较4.4 分析4.5…

Linux下 Docker容器引擎基础(1)

简述&#xff1a; Docker的容器技术可以在一台主机上轻松为任何应用创建一个轻量级的、可移植的、自给自足的容器。通过这种容器打包应用程序&#xff0c;意味着简化了重新部署、调试这些琐碎的重复工作&#xff0c;极大的提高了工作效率。例如&#xff1a;项目从腾讯云迁移阿…

尚硅谷大数据项目《在线教育之采集系统》笔记002

视频地址&#xff1a;尚硅谷大数据项目《在线教育之采集系统》_哔哩哔哩_bilibili 目录 P032 P033 P033 P034 P035 P036 P032 P033 # 1、定义组件&#xff0c;为各组件命名 a1.sources r1 a1.channels c1 a1.sinks - k1# 2、配置sources&#xff0c;描述source a1.sour…

ALLEGRO之Route菜单

本文主要介绍了ALLEGRO的Route菜单。 &#xff08;1&#xff09;Connect&#xff1a;走线&#xff1b; &#xff08;2&#xff09;Slide&#xff1a;推挤&#xff1b; &#xff08;3&#xff09;Timing Vision&#xff1a;等长设计时使用&#xff1f;暂不清楚&#xff1b; &…

oracle,获取每日24*60,所有分钟数

前言&#xff1a; 为规范用户的时间录入&#xff0c;因此我们采用下拉的方式&#xff0c;让用户选择需要的时间&#xff0c;因此我们需要将一天24小时的时间拆分为类似00:00,00:01...23:00,23:01,23:59。因此我们需要生成24*601440行的下拉复选值。具体效果如下图所示。 思路 1…

C语言字串函数、内存函数介绍以及模拟实现

目录 前言 本期内容介绍&#xff1a; 一、字符串函数 strlen介绍 strlen 模拟实现&#xff08;三种方式&#xff09; 方法一&#xff1a;计数器法 方法二&#xff1a;递归法&#xff08;不创建临时变量法&#xff09; 方法三&#xff1a;指针-指针 strcpy介绍 strcpy模…

SSIS对SQL Server向Mysql数据转发表数据 (完结)

1、对于根据主键进行更新和插入新的数据&#xff0c;根据前面的文章&#xff0c;对于组件已经很熟悉了&#xff0c;我们直接加入一个 查找 组件 &#xff0c;如下所示 2、右键点击"查找"&#xff0c;然后“编辑” &#xff0c;选择“连接”,选中我们的目标连接器&…

Vue2 第七节 Vue监测数据更新原理

&#xff08;1&#xff09;Vue会监视data中所有层次的数据 &#xff08;2&#xff09;如何监测对象中的数据 通过setter实现监视&#xff0c;且要在new Vue时传入要监测的数据对象中后追加的属性&#xff0c;Vue默认不做响应式处理如果要给后添加的属性做响应式&#xff0c;使…

Docker私有仓库

Docker私有仓库 Docker官方的Docker hub&#xff08;https://hub.docker.com&#xff09;是一个用于管理公共镜像的仓库&#xff0c;我们可以从上面拉取镜像到本地&#xff0c;也可以把我们自己的镜像推送上去。但是&#xff0c;有时候我们的服务器无法访问互联网&#xff0c;…

初阶数据结构——二叉树题目

文章目录 一、单值二叉树二、检查两颗树是否相同三、另一棵树的子树四、二叉树的前序遍历五、对称二叉树 一、单值二叉树 单值二叉树 如果二叉树每个节点都具有相同的值&#xff0c;那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时&#xff0c;才返回 true&#xff…

Docker学习笔记,包含docker安装、常用命令、dockerfile、docker-compose等等

&#x1f600;&#x1f600;&#x1f600;创作不易&#xff0c;各位看官点赞收藏. 文章目录 Docker 学习笔记1、容器2、Docker 安装3、Docker 常用命令4、Docker 镜像5、自定义镜像5.1、镜像推送到阿里云5.2、镜像私有库 6、数据卷7、Docker 软件安装8、Docker File8.1、常见保…

基于python+Xception算法模型实现一个图像分类识别系统

一、目录 Xception介绍数据集处理模型训练模型评估项目扩展 二、Xception介绍 在计算机视觉领域&#xff0c;图像识别是一个非常重要的任务&#xff0c;其应用涵盖了人脸识别、物体检测、场景理解等众多领域。随着深度学习技术的发展&#xff0c;深度卷积神经网络&#xff0…

哈工大计算机网络课程网络安全基本原理之:身份认证

哈工大计算机网络课程网络安全基本原理之&#xff1a;身份认证 在日常生活中&#xff0c;在很多场景下我们都需要对当前身份做认证&#xff0c;比如使用密码、人脸识别、指纹识别等&#xff0c;这些都是身份认证的常用方式。本节介绍的身份认证&#xff0c;是在计算机网络安全…

android 如何分析应用的内存(十三)——perfetto

android 如何分析应用的内存&#xff08;十三&#xff09; 本篇文章是native内存的最后一篇文章——perfetto perfetto简介 从2018年始&#xff0c;android开发者峰会正式推出perfetto工具。从此perfetto成为安卓最重要的工具之一。在2018年以前&#xff0c;android使用syst…

OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装

OpenHarmony开源鸿蒙学习入门 - 基于3.2Release 应用开发环境安装 基于目前官方master主支&#xff0c;最新文档版本3.2Release&#xff0c;更新应用开发环境安装文档。 一、安装IDE&#xff1a; 1.IDE安装的系统要求 2.IDE下载官网链接&#xff08;IDE下载链接&#xff09; …

小红书2020校招测试开发后端笔试题卷三

//完全背包求组合数 #include <iostream> #include<vector> #include<set> #include<map> #include<algorithm> using namespace std; int value[300]; // vector<int>vis; // vector<int>vis1; map<vector<int>,int>m…

Tomcat的基本使用,如何用Maven创建Web项目、开发完成部署的Web项目

Tomcat 一、Tomcat简介二、Tomcat基本使用三、Maven创建Web项目3.1 Web项目结构3.2开发完成部署的Web项目3.3创建Maven Web项目3.3.1方式一3.3.2方式二&#xff08;个人推荐&#xff09; 总结 一、Tomcat简介 Web服务器&#xff1a; Web服务器是一个应用程序&#xff08;软件&…

深入探究Java面向对象的三大特征:封装、继承、多态

文章目录 1. 封装&#xff08;Encapsulation&#xff09;2. 继承&#xff08;Inheritance&#xff09;3. 多态&#xff08;Polymorphism&#xff09;结语 导语&#xff1a;Java是一门面向对象的编程语言&#xff0c;其核心思想是将现实世界中的事物抽象成对象&#xff0c;并通过…

PACS系统源码:支持三维重建功能、集成放射科管理RIS系统、图文报告编辑、打印、多级审核机制

PACS系统源码 PACS系统是以最新的IT技术为基础&#xff0c;遵循医疗卫生行业IHE/DICOM3.0和HL7标准&#xff0c;开发的多功能服务器和阅片系统。通过简单高性能的阅片功能&#xff0c;支持繁忙时的影像诊断业务&#xff0c;拥有保存影像的院内Web传输及离线影像等功能&#xf…