机器学习最经典算法-SVM支持向量机-【基本解读算法+详细实际案例分部流程】

支持向量机(SVM)

SVM算法可谓是最经典的机器学习算法了,具有泛化错误率低,分类速度快,结果易解释等特点多多,在应用领域涉及非常广,比如人像识别 、文本分类 、手写字符识别、人脸识别、生物信息学等等等,同时算法模型评估效果也是很优秀的,它为何这么优秀?实际背后其实是数学凸优化问题,即:局部最优解,一定是全局最优解【不好理解!】,你可以类比于高中线性优化问题的直线的平移问题【肤浅的理解】
有兴趣可以参考这篇文章【传送门】

支持向量机要解决的问题

假设有这么些点,画条线,把它们分成两堆!很easy!

一维
很容易用一条点【这点有点长哈哈哈】来分开!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nUBs8b3m-1618940233287)(attachment:image.png)]

二维:用一条线

在这里插入图片描述

跟我画的一样叭?

在这里插入图片描述

三维:用一个面

在这里插入图片描述

n维:寻找超平面

到这里,你应该有一个大致的印象,SVM大致要干什么了!SVM的理论逻辑部分,全是数学推导!
比如对距离的定义,目标函数、拉格朗日乘子法、核函数等等,有点让人头大!
那下面就开始加速了!来案例实操!上代码!

SVM基本模型

基于SVM的和核心概念以及数学推导,完成初级建模

导入包

这里是全部的包展示,在后面的代码中会陆陆续续使用到

%matplotlib inline  
#为了在notebook中画图展示
import numpy as np #用于科学计算
import matplotlib.pyplot as plt #画图
from scipy import stats #统计函数,scipy执行数学,科学和工程计算,依赖于numpy
import seaborn as sns; sns.set() # seaborn同matplotlib一样,是matplotlib的高级封装,画图更好看,更简单。
from sklearn.datasets.samples_generator import make_blobs
from sklearn.svm import SVC 
from sklearn.datasets.samples_generator import make_circles
from mpl_toolkits import mplot3d
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report
from sklearn.metrics import confusion_matrix

数据导入

我们这里使用sklearn模块里面的datasets生成一些数据。

#随机来点数据
#其中 cluster_std是数据的离散程度
from sklearn.datasets.samples_generator import make_blobs
X, y = make_blobs(n_samples=50, centers=2,
                  random_state=0, cluster_std=0.60)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='PiYG')
<matplotlib.collections.PathCollection at 0x1f17f8d8648>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fjAThsru-1618940233290)(output_19_1.png)]

datasets.samples_generator是sklearn工具包的数据生成函数,可以定义生成数据结构
make_blobs是另一个函数,其中的参数设置
n_samples=50:定义样本数目,50个点
centers=2:数据簇2个
random_state=0:随机状态,保证每次不变
cluster_std=0.60:离散程度

上述代码,一共构建了50个点,要进行二分类任务,从输出结果来看,这些点很容易分开,随便画!

随便的画几条分割线,哪个呢?这是一个问题!!

#随便的画几条分割线,哪个好来这?
xfit = np.linspace(-1, 3.5) #产生序列
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='PiYG')

for m, b in [(1, 0.65), (0.5, 1.6), (-0.2, 2.9)]:
    plt.plot(xfit, m * xfit + b, '-')
#限制一下X的取值范围
plt.xlim(-1, 3.5);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-78mIBK90-1618940233291)(output_23_0.png)]

我们绘制了3条不同的决策边界,也完全符合要求,但是那条最好呢?
这就是支持向量机最基本的问题了——如何寻找最优决策边界?
为了提高模型的泛化能力,中间可以看成隔离带,隔离带越宽,泛化能力越好,效果最好
打个比方!找男朋友,你想找个心胸宽广的还是心胸狭隘的?

Support Vector Machines: 最小化 雷区

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')

for m, b, d in [(1, 0.65, 0.33), (0.5, 1.6, 0.55), (-0.2, 2.9, 0.2)]:
    yfit = m * xfit + b
    plt.plot(xfit, yfit, '-k')
    plt.fill_between(xfit, yfit - d, yfit + d, edgecolor='none',
                     color='#AAAAAA', alpha=0.4)

plt.xlim(-1, 3.5);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hu2srawG-1618940233294)(output_26_0.png)]

好像宽度差别不太大!肉眼看不出来啊!臣妾做不到啊!
咋办?

请SVM自己来选吧,看看它怎么抉择这个边界的

训练一个基本的SVM

#分类任务
from sklearn.svm import SVC 
#线性核函数 相当于不对数据进行变换
model = SVC(kernel='linear') # 实例化模型
model.fit(X, y) # 模型训练
SVC(kernel='linear')
核函数的选择很重要

我们选择的是线性核函数,参数值默认,看效果

#绘图函数
def plot_svc_decision_function(model, ax=None, plot_support=True):
   
    if ax is None:
        ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    
    # 用SVM自带的decision_function函数来绘制
    x = np.linspace(xlim[0], xlim[1], 30)
    y = np.linspace(ylim[0], ylim[1], 30)
    Y, X = np.meshgrid(y, x)
    xy = np.vstack([X.ravel(), Y.ravel()]).T
    P = model.decision_function(xy).reshape(X.shape)
    
    # 绘制决策边界
    ax.contour(X, Y, P, colors='k',
               levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])
    
    # 绘制支持向量
    if plot_support:
        ax.scatter(model.support_vectors_[:, 0],
                   model.support_vectors_[:, 1],
                   s=300, linewidth=1, alpha=0.2);
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
plot_svc_decision_function(model)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-njJxZDEH-1618940233296)(output_34_0.png)]

  • 这条线就是我们希望得到的决策边界啦

  • 观察发现有3个点做了特殊的标记,它们恰好都是边界上的点

  • 它们就是我们的support vectors(支持向量)

  • Scikit-Learn中, 它们存储在这个位置 support_vectors_(一个属性)

model.support_vectors_
array([[ 0.44359863,  3.11530945],
       [ 2.33812285,  3.43116792],
       [ 2.06156753,  1.96918596]])
  • 观察可以发现,只需要支持向量我们就可以把模型构建出来

  • 接下来我们尝试一下,用不同多的数据点,看看效果会不会发生变化

  • 分别使用60个和120个数据点

def plot_svm(N=10, ax=None):
    X, y = make_blobs(n_samples=200, centers=2,
                      random_state=0, cluster_std=0.60)
    X = X[:N]
    y = y[:N]
    model = SVC(kernel='linear', C=1E10)
    model.fit(X, y)
    
    ax = ax or plt.gca()
    ax.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    ax.set_xlim(-1, 4)
    ax.set_ylim(-1, 6)
    plot_svc_decision_function(model, ax)
# 分别对不同的数据点进行绘制
fig, ax = plt.subplots(1, 2, figsize=(16, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
for axi, N in zip(ax, [60, 120]):
    plot_svm(N, axi)
    axi.set_title('N = {0}'.format(N))

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TWWEVXS4-1618940233298)(output_38_0.png)]

  • 左边是60个点的结果,右边的是120个点的结果
  • 观察发现,只要支持向量没变,其他的数据怎么加无所谓!

引入核函数的SVM

  • 首先我们先用线性的核来看一下在下面这样比较难的数据集上还能分了吗?

  • 继续提速!

  • 刚才我们datasets.samples_generator产生簇形,好分类。

  • 这里用make_circles产生环形数据,加大游戏难度,看看SVM能解决问题不?

from sklearn.datasets.samples_generator import make_circles
# 绘制另外一种数据集
X, y = make_circles(100, factor=.1, noise=.1)
#看看这回线性和函数能解决嘛
clf = SVC(kernel='linear').fit(X, y)

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
plot_svc_decision_function(clf, plot_support=False);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJAQ6tV9-1618940233301)(output_42_0.png)]

  • noise: 双倍或无(默认=无)
    高斯噪声的标准偏差加到数据上。
  • factor : 0 <double <1(默认值= .8)
    内圈和外圈之间的比例因子。

拟合的结果,明显不行。二维空间更本分不开!

  • 坏菜喽,分不了了,那咋办呢?试试高维核变换吧!
  • 这就好比你和你男朋友现在在学校里藕断丝连,当步入社会,你们要考虑财迷油盐、以及结婚生子的问题时,从更高维的角度去思考,你觉得社会这个大熔炉,会很轻易的把你们分开!
  • 但是成长一直在路上,陪伴也一直在路上,且行且珍惜

解释高维变换

  • 以一维为例,好理解些

这里是1维数据,很显然,一个点是不可能将红点和绿点分开,我们引入一个函数 y = x^2

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U99YYzbT-1618940233302)(attachment:image.png)]

将其转换为二维了,这些点就起来了!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y2f81CUV-1618940233306)(attachment:image.png)]

我们这时找到一条线,就可以把这些点分开了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pwEwjJ5h-1618940233307)(attachment:image.png)]

用二维手段处理一维数据,这就是降维打击!!!!

#加入了新的维度r
from mpl_toolkits import mplot3d
r = np.exp(-(X ** 2).sum(1))
# 可以想象一下在三维中把环形数据集进行上下拉伸
def plot_3D(elev=30, azim=30, X=X, y=y):
    ax = plt.subplot(projection='3d')
    ax.scatter3D(X[:, 0], X[:, 1], r, c=y, s=50, cmap='autumn')
    ax.view_init(elev=elev, azim=azim)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('r')

plot_3D(elev=45, azim=45, X=X, y=y)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yPDgwdnb-1618940233309)(output_54_0.png)]

#加入高斯核函数
clf = SVC(kernel='rbf') # 以前是线性
clf.fit(X, y)
SVC()
#这回厉害了!
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
plot_svc_decision_function(clf)
plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
            s=300, lw=1, facecolors='none');

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tlCEzXP-1618940233311)(output_56_0.png)]

使用这种核支持向量机,我们学习一个合适的非线性决策边界。这种核变换策略在机器学习中经常被使用!

调节SVM参数: Soft Margin问题

调节C参数

  • 当C趋近于无穷大时:意味着分类严格不能有错误
  • 当C趋近于很小的时:意味着可以有更大的错误容忍
这里有一个模型的过拟合问题,训练好的模型,应用到实际情况,如果出现过拟合,就会导致,实际应用的泛化性能差
# 这份数据集中cluster_std稍微大一些,这样才能体现出软间隔的作用
X, y = make_blobs(n_samples=100, centers=2,
                  random_state=0, cluster_std=0.8) # 刚才取的0.6
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
<matplotlib.collections.PathCollection at 0x1f103496e48>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MvDlvWB2-1618940233312)(output_60_1.png)]

看松弛因子C发挥的作用

#加大游戏难度的数据集
X, y = make_blobs(n_samples=100, centers=2,
                  random_state=0, cluster_std=0.8)

fig, ax = plt.subplots(1, 2, figsize=(16, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
# 选择两个C参数来进行对别实验,分别为10和0.1
for axi, C in zip(ax, [10.0, 0.1]):
    model = SVC(kernel='linear', C=C).fit(X, y)
    axi.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    plot_svc_decision_function(model, axi)
    axi.scatter(model.support_vectors_[:, 0],
                model.support_vectors_[:, 1],
                s=300, lw=1, facecolors='none');
    axi.set_title('C = {0:.1f}'.format(C), size=14)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HlJlvyPy-1618940233313)(output_62_0.png)]

  • 松弛因子分别是10和0.1,其他不变
  • C=10,分类严格,符合要求,但是可以发现,这个不够宽。
  • C=0.1,分类宽松,但是分类的有些点不合符要求,对于机器学习来讲,有点错误我们是可以容忍的,虽然越界,但是它的宽度大,模型应用的泛化性能好!

调节gamma参数选择

高斯核函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WzTgeH7t-1618940233314)(attachment:image.png)]

  • gamma就是这个西格玛!
  • gamma值越大,模型复杂程度越高,反之越低。
X, y = make_blobs(n_samples=100, centers=2,
                  random_state=0, cluster_std=1.1)

fig, ax = plt.subplots(1, 2, figsize=(16, 6))
fig.subplots_adjust(left=0.0625, right=0.95, wspace=0.1)
# 选择不同的gamma值来观察建模效果
for axi, gamma in zip(ax, [10.0, 0.1]):
    model = SVC(kernel='rbf', gamma=gamma).fit(X, y)
    axi.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
    plot_svc_decision_function(model, axi)
    axi.scatter(model.support_vectors_[:, 0],
                model.support_vectors_[:, 1],
                s=300, lw=1, facecolors='none');
    axi.set_title('gamma = {0:.1f}'.format(gamma), size=14)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OGmjIvlL-1618940233316)(output_68_0.png)]

  • gamma=10,训练模型比较复杂,但是出现过拟合风险大。
  • gamma=0.1,训练模型比较简单,模型决策边界比较平稳。

总体来讲,作为调参侠,我们希望我们的模型,别太复杂,泛化能力强一点,这样才能解决实际问题

Example: Face Recognition 人脸识别

As an example of support vector machines in action, let’s take a look at the facial recognition problem.
We will use the Labeled Faces in the Wild dataset, which consists of several thousand collated photos of various public figures.
A fetcher for the dataset is built into Scikit-Learn:

  • 还是运用sklearn里面的数据集,人脸识别
  • 任务:让机器来通过人物图像,来猜出他(她)是谁

第一步:导入数据

#读取数据集
from sklearn.datasets import fetch_lfw_people
faces = fetch_lfw_people(min_faces_per_person=60)
#看一下数据的规模
print(faces.target_names)
print(faces.images.shape)
['Ariel Sharon' 'Colin Powell' 'Donald Rumsfeld' 'George W Bush'
 'Gerhard Schroeder' 'Hugo Chavez' 'Junichiro Koizumi' 'Tony Blair']
(1348, 62, 47)
fig, ax = plt.subplots(3, 5)
for i, axi in enumerate(ax.flat):
    axi.imshow(faces.images[i], cmap='bone')
    axi.set(xticks=[], yticks=[],
            xlabel=faces.target_names[faces.target[i]])

在这里插入图片描述

Let’s plot a few of these faces to see what we’re working with:

  • 一个人限制至少60张图片,一共1348个人物图像
  • 每个图的大小是 [62×47]

第二步:数据降维及其划分

  • 在这里我们就把每一个像素点当成了一个特征,但是这样特征太多了,用PCA降维一下吧!
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline

#降维到150维
pca = PCA(n_components=150, whiten=True, random_state=42)
svc = SVC(kernel='rbf', class_weight='balanced')
#先降维然后再SVM
model = make_pipeline(pca, svc)

数据降到150维,先把基本模型实例化,在建模。由于要对模型进行评估,所以要划分数据集,为训练集合测试集

from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(faces.data, faces.target,
                                                random_state=40)

第三步:模型训练

使用grid search cross-validation来选择我们的参数 简称网格搜索,实际就是“搞(一个一个试)”

前文我们提高调解松弛因子C和gamma

from sklearn.model_selection import GridSearchCV
param_grid = {'svc__C': [1, 5, 10],
              'svc__gamma': [0.0001, 0.0005, 0.001]}
grid = GridSearchCV(model, param_grid)

%time grid.fit(Xtrain, ytrain)
print(grid.best_params_)
Wall time: 22.8 s
{'svc__C': 5, 'svc__gamma': 0.001}

第四步:结果预测与评估

model = grid.best_estimator_
yfit = model.predict(Xtest)
print(yfit.shape)
fig, ax = plt.subplots(4, 6)
for i, axi in enumerate(ax.flat):
    axi.imshow(Xtest[i].reshape(62, 47), cmap='bone')
    axi.set(xticks=[], yticks=[])
    axi.set_ylabel(faces.target_names[yfit[i]].split()[-1],
                   color='black' if yfit[i] == ytest[i] else 'red')
fig.suptitle('Predicted Names; Incorrect Labels in Red', size=14);
(337,)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-45Z6LUVK-1618940233317)(output_86_1.png)]

想获得各项具体评估指标,在sklearn中有一个非常方便的函数

from sklearn.metrics import classification_report
print(classification_report(ytest, yfit,
                            target_names=faces.target_names))
                   precision    recall  f1-score   support

     Ariel Sharon       0.50      0.50      0.50        16
     Colin Powell       0.69      0.81      0.75        54
  Donald Rumsfeld       0.83      0.85      0.84        34
    George W Bush       0.94      0.88      0.91       136
Gerhard Schroeder       0.72      0.85      0.78        27
      Hugo Chavez       0.81      0.72      0.76        18
Junichiro Koizumi       0.87      0.87      0.87        15
       Tony Blair       0.85      0.76      0.80        37

         accuracy                           0.82       337
        macro avg       0.78      0.78      0.78       337
     weighted avg       0.83      0.82      0.82       337
  • 精度(precision) = 正确预测的个数(TP)/被预测正确的个数(TP+FP)
  • 召回率(recall)=正确预测的个数(TP)/预测个数(TP+FN)
  • F1 = 2精度召回率/(精度+召回率)

看起来效果还可以,我们使用混淆矩阵更容易方便观察

from sklearn.metrics import confusion_matrix
mat = confusion_matrix(ytest, yfit)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
            xticklabels=faces.target_names,
            yticklabels=faces.target_names)
plt.xlabel('true label')
plt.ylabel('predicted label');

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YH6XrEmK-1618940233319)(output_91_0.png)]

  • 这样显示出来能帮助我们查看哪些人更容易弄混

  • 对角线的数值表示将一个人正确预测成他自己的样本个数

  • 第一列 Ariel Sharon,测试集包含16个样本,正确划分有8个,一个错分为Donald Rumsfeld,另一个错分为Gerhard Schroeder

剧终

热门文章

暂无图片
编程学习 ·

那些年让我们目瞪口呆的bug

程序员一生与bug奋战&#xff0c;可谓是杀敌无数&#xff0c;见怪不怪了&#xff01;在某知识社交平台中&#xff0c;一个“有哪些让程序员目瞪口呆的bug”的话题引来了6700多万的阅读&#xff0c;可见程序员们对一个话题的敏感度有多高。 1、麻省理工“只能发500英里的邮件” …
暂无图片
编程学习 ·

redis的下载与安装

下载redis wget http://download.redis.io/releases/redis-5.0.0.tar.gz解压redis tar -zxvf redis-5.0.0.tar.gz编译 make安装 make install快链方便进入redis ln -s redis-5.0.0 redis
暂无图片
编程学习 ·

《大话数据结构》第三章学习笔记--线性表(一)

线性表的定义 线性表&#xff1a;零个或多个数据元素的有限序列。 线性表元素的个数n定义为线性表的长度。n为0时&#xff0c;为空表。 在比较复杂的线性表中&#xff0c;一个数据元素可以由若干个数据项组成。 线性表的存储结构 顺序存储结构 可以用C语言中的一维数组来…
暂无图片
编程学习 ·

对象的扩展

文章目录对象的扩展属性的简洁表示法属性名表达式方法的name属性属性的可枚举性和遍历可枚举性属性的遍历super关键字对象的扩展运算符解构赋值扩展运算符AggregateError错误对象对象的扩展 属性的简洁表示法 const foo bar; const baz {foo}; baz // {foo: "bar"…
暂无图片
编程学习 ·

让程序员最头疼的5种编程语言

世界上的编程语言&#xff0c;按照其应用领域&#xff0c;可以粗略地分成三类。 有的语言是多面手&#xff0c;在很多不同的领域都能派上用场。大家学过的编程语言很多都属于这一类&#xff0c;比如说 C&#xff0c;Java&#xff0c; Python。 有的语言专注于某一特定的领域&…
暂无图片
编程学习 ·

写论文注意事项

参考链接 给研究生修改了一篇论文后&#xff0c;该985博导几近崩溃…… 重点分析 摘要与结论几乎重合 这一条是我见过研究生论文中最常出现的事情&#xff0c;很多情况下&#xff0c;他们论文中摘要部分与结论部分重复率超过70%。对于摘要而言&#xff0c;首先要用一小句话引…
暂无图片
编程学习 ·

安卓 串口开发

上图&#xff1a; 上码&#xff1a; 在APP grable添加 // 串口 需要配合在项目build.gradle中的repositories添加 maven {url "https://jitpack.io" }implementation com.github.licheedev.Android-SerialPort-API:serialport:1.0.1implementation com.jakewhart…
暂无图片
编程学习 ·

2021-2027年中国铪市场调研与发展趋势分析报告

2021-2027年中国铪市场调研与发展趋势分析报告 本报告研究中国市场铪的生产、消费及进出口情况&#xff0c;重点关注在中国市场扮演重要角色的全球及本土铪生产商&#xff0c;呈现这些厂商在中国市场的铪销量、收入、价格、毛利率、市场份额等关键指标。此外&#xff0c;针对…
暂无图片
编程学习 ·

Aggressive cows题目翻译

描述&#xff1a; Farmer John has built a new long barn, with N (2 < N < 100,000) stalls.&#xff08;John农民已经新建了一个长畜棚带有N&#xff08;2<N<100000&#xff09;个牛棚&#xff09; The stalls are located along a straight line at positions…
暂无图片
编程学习 ·

剖析组建PMO的6个大坑︱PMO深度实践

随着事业环境因素的不断纷繁演进&#xff0c;项目时代正在悄悄来临。设立项目经理转岗、要求PMP等项目管理证书已是基操&#xff0c;越来越多的组织开始组建PMO团队&#xff0c;大有曾经公司纷纷建造中台的气质&#xff08;当然两者的本质并不相同&#xff0c;只是说明这个趋势…
暂无图片
编程学习 ·

Flowable入门系列文章118 - 进程实例 07

1、获取流程实例的变量 GET运行时/进程实例/ {processInstanceId} /变量/ {变量名} 表1.获取流程实例的变量 - URL参数 参数需要值描述processInstanceId是串将流程实例的id添加到变量中。变量名是串要获取的变量的名称。 表2.获取流程实例的变量 - 响应代码 响应码描述200指…
暂无图片
编程学习 ·

微信每天自动给女[男]朋友发早安和土味情话

微信通知&#xff0c;每天给女朋友发早安、情话、诗句、天气信息等~ 前言 之前逛GitHub的时候发现了一个自动签到的小工具&#xff0c;b站、掘金等都可以&#xff0c;我看了下源码发现也是很简洁&#xff0c;也尝试用了一下&#xff0c;配置也都很简单&#xff0c;主要是他有一…
暂无图片
编程学习 ·

C语言二分查找详解

二分查找是一种知名度很高的查找算法&#xff0c;在对有序数列进行查找时效率远高于传统的顺序查找。 下面这张动图对比了二者的效率差距。 二分查找的基本思想就是通过把目标数和当前数列的中间数进行比较&#xff0c;从而确定目标数是在中间数的左边还是右边&#xff0c;将查…
暂无图片
编程学习 ·

项目经理,你有什么优势吗?

大侠被一个问题问住了&#xff1a;你和别人比&#xff0c;你的优势是什么呢? 大侠听到这个问题后&#xff0c;脱口而出道&#xff1a;“项目管理能力和经验啊。” 听者抬头看了一下大侠&#xff0c;显然听者对大侠的这个回答不是很满意&#xff0c;但也没有继续追问。 大侠回家…
暂无图片
编程学习 ·

nginx的负载均衡和故障转移

#注&#xff1a;proxy_temp_path和proxy_cache_path指定的路径必须在同一分区 proxy_temp_path /data0/proxy_temp_dir; #设置Web缓存区名称为cache_one&#xff0c;内存缓存空间大小为200MB&#xff0c;1天没有被访问的内容自动清除&#xff0c;硬盘缓存空间大小为30GB。 pro…
暂无图片
编程学习 ·

业务逻辑漏洞

身份认证安全 绕过身份认证的几种方法 暴力破解 测试方法∶在没有验证码限制或者一次验证码可以多次使用的地方&#xff0c;可以分为以下几种情况︰ (1)爆破用户名。当输入的用户名不存在时&#xff0c;会显示请输入正确用户名&#xff0c;或者用户名不存在 (2)已知用户名。…