KNN k近邻

文章目录

  • KNN算法
  • K近邻中近邻的距离度量
    • 欧式距离
    • 标准化欧式距离
    • 曼哈顿距离
    • 汉明距离
    • 夹角余弦
    • 杰卡德相似系数
    • 皮尔逊系数
    • 切比雪夫距离
    • 闵可夫斯基距离
    • 马氏距离
    • 巴氏距离
    • 各种“距离”的应用场景
    • 距离函数之间的等价关系
  • K近邻中K值的选择
  • KNN最近邻分类算法的过程
  • 基于KNN的手写字体识别分类实践

KNN算法

何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1时,算法便成了最近邻算法,即寻找最近的那个邻居。

用官方的话来说,所谓K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例(也就是上面所说的K个邻居),这K个实例的多数属于某个类,就把该输入实例分类到这个类中。

  • 如上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。也就是说,现在,我们不知道中间那个绿色的数据是从属于哪一类(蓝色小正方形or红色小三角形),KNN就是解决这个问题的。

  • 如果K=3,绿色圆点的最近的3个邻居是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。

  • 如果K=5,绿色圆点的最近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。

于此我们看到,当无法判定当前待分类点是从属于已知分类中的哪一类时,我们可以依据统计学的理论看它所处的位置特征,衡量它周围邻居的权重,而把它归为(或分配)到权重更大的那一类。这就是K近邻算法的核心思想。

K近邻中近邻的距离度量

我们看到,K近邻算法的核心在于找到实例点的邻居,这个时候,问题就接踵而至了,如何找到邻居,邻居的判定标准是什么,用什么来度量。这一系列问题便是下面要讲的距离度量表示法。

欧式距离

重要

最常见的两点之间或多点之间的距离表示法,又称之为欧几里得度量,它定义于欧几里得空间中,如
点x=(x1,...,xn)和y=(y1,...,yn)之间的距离为:d(x,y)=(x1−y1)2+(x2−y2)2+..+(xn−yn)2=Σni=1(xi−yi)2点x=(x_1,...,x_n)和y=(y_1,...,y_n)之间的距离为: \\ d\left( x,y \right) =\sqrt{\left( x_1-y_1 \right) ^2\,\,+\,\,\left( x_2-y_2 \right) ^2+..+\left( x_n-y_n \right) ^2}=\sqrt{\underset{i=1}{\overset{n}{\varSigma}}\left( x_i-y_i \right) ^2} 点x=(x1​,...,xn​)和y=(y1​,...,yn​)之间的距离为:d(x,y)=(x1​−y1​)2+(x2​−y2​)2+..+(xn​−yn​)2​=i=1Σn​(xi​−yi​)2​

  • 二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离:

    d12=(x1−x2)2+(y1−y2)2d_{12}=\sqrt{\left( x_1-x_2 \right) ^2\,\,+\,\,\left( y_1-y_2 \right) ^2} d12​=(x1​−x2​)2+(y1​−y2​)2​

  • 三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:

    d12=(x1−x2)2+(y1−y2)2+(z1−z2)2d_{12}=\sqrt{\left( x_1-x_2 \right) ^2\,\,+\,\,\left( y_1-y_2 \right) ^2+\,\,\left( z_1-z_2 \right) ^2} d12​=(x1​−x2​)2+(y1​−y2​)2+(z1​−z2​)2​

  • 两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:

    d12=Σnk=1(x1k−x2k)2d_{12}=\sqrt{\underset{k=1}{\overset{n}{\varSigma}}\left( x_{1k}-x_{2k} \right) ^2} d12​=k=1Σn​(x1k​−x2k​)2​

    也可以用表示成向量运算的形式:

    d12=(a−b)(a−b)Td_{12}=\sqrt{\left( a-b \right) \left( a-b \right) ^T} d12​=(a−b)(a−b)T​

标准化欧式距离

重要

准化欧氏距离是针对简单欧氏距离的缺点而作的一种改进方案。标准欧氏距离的思路:既然数据各维分量的分布不一样,那先将各个分量都“标准化”到均值、方差相等。至于均值和方差标准化到多少,先复习点统计学知识。

假设样本集X的数学期望或均值(mean)为m,标准差(standard deviation,方差开根)为s,那么X的“标准化变量”X*表示为:(X-m)/s,而且标准化变量的数学期望为0,方差为1。
即,样本集的标准化过程(standardization)用公式描述就是:

X∗=X−msX^*=\frac{X-m}{s} X∗=sX−m​

标准化后的值 = ( 标准d化前的值 - 分量的均值 ) /分量的标准差  
经过简单的推导就可以得到两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的标准化欧氏距离的公式:
d12=Σnk=1(x1k−x2ksk)2d_{12}=\sqrt{\underset{k=1}{\overset{n}{\varSigma}}\left( \frac{x_{1k}-x_{2k}}{s_k} \right) ^2} d12​=k=1Σn​(sk​x1k​−x2k​​)2​

曼哈顿距离

重要

我们可以定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。例如在平面上,坐标(x1, y1)的点P1与坐标(x2, y2)的点P2的曼哈顿距离为: ,要注意的是,曼哈顿距离依赖座标系统的转度,而非系统在座标轴上的平移或映射。

通俗来讲,想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,驾驶距离是两点间的直线距离吗?显然不是,除非你能穿越大楼。而实际驾驶距离就是这个“曼哈顿距离”,此即曼哈顿距离名称的来源, 同时,曼哈顿距离也称为城市街区距离(City Block distance)。

  • 二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离

    d12=∣x1−x2∣+∣y1−y2∣d_{12}=|x_1-x_2| +\,\,|y_1-y_2| d12​=∣x1​−x2​∣+∣y1​−y2​∣

  • 两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的曼哈顿距离

    d12=Σnk=1∣x1k−x2k∣d_{12}=\underset{k=1}{\overset{n}{\varSigma}}|x_{1k}-x_{2k}| d12​=k=1Σn​∣x1k​−x2k​∣

汉明距离

重要

两个等长字符串s1与s2之间的汉明距离定义为将其中一个变为另外一个所需要作的最小替换次数。例如字符串“1111”与“1001”之间的汉明距离为2。应用:信息编码(为了增强容错性,应使得编码间的最小汉明距离尽可能大)。

夹角余弦

重要

几何中夹角余弦可用来衡量两个向量方向的差异,机器学习中借用这一概念来衡量样本向量之间的差异。

  • 在二维空间中向量A(x1,y1)与向量B(x2,y2)的夹角余弦公式:

    cos⁡θ=x1x2+y1y2(x12+y12)(x22+y22)\cos \theta =\frac{x_1x_2+y_1y_2}{\sqrt{\left( {x_1}^2+{y_1}^2 \right)}\sqrt{\left( {x_2}^2+{y_2}^2 \right)}} cosθ=(x1​2+y1​2)​(x2​2+y2​2)​x1​x2​+y1​y2​​

  • 两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦:

    cos⁡θ=a⋅b∣a∣∣b∣\cos \theta =\frac{a\cdot b}{|a||b|} cosθ=∣a∣∣b∣a⋅b​

夹角余弦取值范围为[-1,1]。夹角余弦越大表示两个向量的夹角越小,夹角余弦越小表示两向量的夹角越大。当两个向量的方向重合时夹角余弦取最大值1,当两个向量的方向完全相反夹角余弦取最小值-1。

杰卡德相似系数

重要

两个集合A和B的交集元素在A,B的并集中所占的比例,称为两个集合的杰卡德相似系数,用符号J(A,B)表示。杰卡德相似系数是衡量两个集合的相似度一种指标。
J(A,B)=∣A∩B∣∣A∪B∣J\left( A,B \right) =\frac{|A\cap B|}{|A\cup B|} J(A,B)=∣A∪B∣∣A∩B∣​

与杰卡德相似系数相反的概念是杰卡德距离:
Jδ(A,B)=1−J(A,B)=∣A∪B∣−∣A∩B∣∣A∪B∣J_{\delta}\left( A,B \right) =1-J\left( A,B \right) =\frac{|A\cup B|-|A\cap B|}{|A\cup B|} Jδ​(A,B)=1−J(A,B)=∣A∪B∣∣A∪B∣−∣A∩B∣​

皮尔逊系数

重要

统计学中,皮尔逊积矩相关系数用于度量两个变量X和Y之间的相关(线性相关),其值介于-1与1之间。通常情况下通过以下取值范围判断变量的相关强度:
皮尔森相关系数等于两个变量的协方差除于两个变量的标准差

0.8-1.0     极强相关
0.6-0.8     强相关
0.4-0.6     中等程度相关
0.2-0.4     弱相关
0.0-0.2     极弱相关或无相关

切比雪夫距离

若二个向量或二个点p 、and q,其座标分别为Pi及qi,则两者之间的切比雪夫距离定义如下:

这也等于以下Lp度量的极值: ,因此切比雪夫距离也称为L∞度量。

以数学的观点来看,切比雪夫距离是由一致范数(uniform norm)(或称为上确界范数)所衍生的度量,也是超凸度量(injective metric space)的一种。

在平面几何中,若二点p及q的直角坐标系坐标为(x1,y1)及(x2,y2),则切比雪夫距离为:

玩过国际象棋的朋友或许知道,国王走一步能够移动到相邻的8个方格中的任意一个。那么国王从格子(x1,y1)走到格子(x2,y2)最少需要多少步?。你会发现最少步数总是max( | x2-x1 | , | y2-y1 | ) 步 。有一种类似的一种距离度量方法叫切比雪夫距离。

  • 二维平面两点a(x1,y1)与b(x2,y2)间的切比雪夫距离 :

  • 两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的切比雪夫距离:

闵可夫斯基距离

(Minkowski Distance),闵氏距离不是一种距离,而是一组距离的定义。

两个n维变量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的闵可夫斯基距离定义为:

其中p是一个变参数。
当p=1时,就是曼哈顿距离
当p=2时,就是欧氏距离
当p→∞时,就是切比雪夫距离
根据变参数的不同,闵氏距离可以表示一类的距离。

马氏距离

有M个样本向量X1~Xm,协方差矩阵记为S,均值记为向量μ,则其中样本向量X到u的马氏距离表示为:

  • 若协方差矩阵是单位矩阵(各个样本向量之间独立同分布),则公式就成了,也就是欧氏距离了:

  • 若协方差矩阵是对角矩阵,公式变成了标准化欧氏距离。

马氏距离的优缺点:量纲无关,排除变量之间的相关性的干扰。

巴氏距离

在统计中,巴氏距离距离测量两个离散或连续概率分布的相似性。它与衡量两个统计样品或种群之间的重叠量的巴氏距离系数密切相关。巴氏距离距离和巴氏距离系数以20世纪30年代曾在印度统计研究所工作的一个统计学家A. Bhattacharya命名。同时,Bhattacharyya系数可以被用来确定两个样本被认为相对接近的,它是用来测量中的类分类的可分离性。

对于离散概率分布 p和q在同一域 X,它被定义为:

其中:

是Bhattacharyya系数。

各种“距离”的应用场景

  • 空间:欧氏距离,
  • 路径:曼哈顿距离,国际象棋国王:切比雪夫距离,
  • 以上三种的统一形式:闵可夫斯基距离,
  • 加权:标准化欧氏距离,
  • 排除量纲和依存:马氏距离,
  • 向量差距:夹角余弦,
  • 编码差别:汉明距离,
  • 集合近似度:杰卡德类似系数与距离,
  • 相关:相关系数与相关距离。

距离函数之间的等价关系

经过标准化后的欧氏距离和余弦相似度,等价于皮尔森相关系数

K近邻中K值的选择

  1. 如果选择较小的K值,就相当于用较小的领域中的训练实例进行预测,“学习”近似误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是“学习”的估计误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
  2. 如果选择较大的K值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
  3. K=N,则完全不足取,因为此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的累,模型过于简单,忽略了训练实例中大量有用信息。

在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法(简单来说,就是一部分样本做训练集,一部分做测试集)来选择最优的K值。

KNN最近邻分类算法的过程

  1. 计算测试样本和训练样本中每个样本点的距离(常见的距离度量有欧式距离,马氏距离等);
  2. 对上面所有的距离值进行排序;
  3. 选前 k 个最小距离的样本;
  4. 根据这 k 个样本的标签进行投票,得到最后的分类类别;

基于KNN的手写字体识别分类实践

在jupyter notebook上测试

from numpy import *
from os import listdir
from collections import Counterdef img2vector(filename):"""将图像数据转换为向量:param filename: 图片文件 因为我们的输入数据的图片格式是 32 * 32的。这个可以打开输入数据文件看看就知道了:return: 一维矩阵该函数将图像转换为向量:该函数创建 1 * 1024 的NumPy数组,然后打开给定的文件,循环读出文件的前32行,并将每行的头32个字符值存储在NumPy数组中,最后返回数组。"""# 创建一个 1 行 1024列 的都为0的一维矩阵returnVect = zeros((1, 1024))# 读取文件fr = open(filename)# 行循环for i in range(32):# 读一行数据lineStr = fr.readline()# 列循环for j in range(32):# 将每个数据转成int类型后放到矩阵里returnVect[0, 32 * i + j] = int(lineStr[j])return returnVect# KNN分类
def classify(inX, dataSet, labels, k):"""inx[1,2,3]DS=[[1,2,3],[1,2,0]]inX: 用于分类的输入向量dataSet: 输入的训练样本集labels: 标签向量k: 选择最近邻居的数目注意:labels元素数目和dataSet行数相同;程序使用欧式距离公式."""# 1.计算距离# 获得数据集大小(shape(0),行数)dataSetSize = dataSet.shape[0]# tile表示将inX向量扩展成dataSetSize项,每项中对原数据集复制1次的数据集。例如,inx[1,2,3],tile(inx,(2,1))=[[1,2,3],[1,2,3]]# diffMat 得到每inX 与 原数据集的差集diffMat = tile(inX, (dataSetSize, 1)) - dataSet# 取平方sqDiffMat = diffMat ** 2# 将矩阵的每一行相加sqDistances = sqDiffMat.sum(axis=1)# 开方distances = sqDistances ** 0.5# 根据距离排序从小到大的排序,返回对应的索引位置# argsort() 是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y。# x=np.array([1,4,3,-1,6,9])# y = x.argsort()# y=[3 0 2 1 4 5]sortedDistIndicies = distances.argsort()# 2. 选择距离最小的k个点# 初始化类别计数(计数个数相当于投票次数)classCount = {}for i in range(k):# 找到该样本的类型voteIlabel = labels[sortedDistIndicies[i]]# 对该类别进行计数累加classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1# 3. 排序并返回出现最多的那个类型 这里max方法是取dict类型的value最大值,并返回其对应的keymaxClassCount = max(classCount, key=classCount.get)return maxClassCount# 手写字体分类测试
def handwritingClassTest():# 1. 导入数据,准备好训练数据# hwLabels存储0~9对应的index位置, trainingMat存放的每个位置对应的图片向量hwLabels = []# load the training settrainingFileList = listdir('trainingDigits')  m = len(trainingFileList)trainingMat = zeros((m, 1024))# 对每个训练文件遍历for i in range(m):# 获取文件名(文件名长这样0_0.txt)fileNameStr = trainingFileList[i]# take off .txtfileStr = fileNameStr.split('.')[0]  # 获得文件对应类别classNumStr = int(fileStr.split('_')[0])# 类别存入标签组hwLabels.append(classNumStr)# 将 32*32的矩阵->1*1024的矩阵[i,:]表示第i行所有列trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr)# 2. 导入测试数据进行测试testFileList = listdir('testDigits')  errorCount = 0.0mTest = len(testFileList)# 遍历测试数据文件列表for i in range(mTest):fileNameStr = testFileList[i]fileStr = fileNameStr.split('.')[0]  # take off .txtclassNumStr = int(fileStr.split('_')[0])# 将测试数据集的 32*32的矩阵->1*1024的一维矩阵vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)# 分类classifierResult = classify(vectorUnderTest, trainingMat, hwLabels, 1)# 打印分类结果print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))if (classifierResult != classNumStr): errorCount += 1.0print("\nthe total number of errors is: %d" % errorCount)print("\nthe total error rate is: %f" % (errorCount / float(mTest)))# 测试执行
handwritingClassTest()

输出

.....
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9
the classifier came back with: 9, the real answer is: 9the total number of errors is: 13the total error rate is: 0.013742

实际使用中,需要对不同的K进行测试,得到最佳的K

  • 测试文件数据说明

    测试文件名是例如0_0.txt、0_1.txt.。。9_0.txt,模式是 具体分类数字_该分类的第几个样本.txt

    其中一份文件数据如下

    00000000000000111000000000000000
    00000000000011111110100000000000
    00000000001111011111110000000000
    00000000001111011111111000000000
    00000000111111111111111000000000
    00000000111111111111111100000000
    00000001111110000000111100000000
    00000011111100000000111100000000
    00000011111100000000011110000000
    00000111111100000000011110000000
    00000011111111000000000111000000
    00000011111110000000000111000000
    00000011111100000000000111000000
    00000011111100000000000111000000
    00000001111000000000001111000000
    00000001111000000000001111000000
    00000001111000000000001111000000
    00000001111000000000001110000000
    00000001111000000000001110000000
    00000001110000000000011110000000
    00000001110000000000011110000000
    00000001110000000000111100000000
    00000011110000000000111100000000
    00000000111100000000111110000000
    00000000111100000000111100000000
    00000000111100000011111100000000
    00000000111110000111111000000000
    00000000011111111111111000000000
    00000000011111111111110000000000
    00000000001111111111000000000000
    00000000001111111111000000000000
    00000000000001101000000000000000

    若有兴趣需要完整测试数据,可以私聊联系我

OK,以上有问题请及时指出

AI基础:KNN与K近邻距离度量说明、利用KNN手写字体识别分类实践相关推荐

  1. 使用KNN和SVM算法实现手写字体识别分类

    下面分别采用的是k近邻算法(KNN)和支持向量机(SVM)算法实现的手写数字识别. 数据集: 百度网盘 提取码:2p50 CSDN资源 项目训练目标 学会调用数据集, 利用Python相关程序从数据集 ...

  2. 基于kNN的手写字体识别——《机器学习实战》笔记

    看完一节<机器学习实战>,算是踏入ML的大门了吧!这里就详细讲一下一个demo:使用kNN算法实现手写字体的简单识别 kNN 先简单介绍一下kNN,就是所谓的K-近邻算法: [作用原理]: ...

  3. 用c语言实现knn算法要有训练集和测试集,KNN算法实战:手写字体识别

    我们已经知道手写字体数据集是一个8×8的矩阵,共有64个特征.让我们看一下K最近邻算法对手写字体数据集处理的效果. 1) 导入相关包 这里我们将用到 datasets 中的手写字体数据,使用 trai ...

  4. 【2017年cs231n学习笔记1】Lecture2 K近邻 距离度量 超参数 交叉验证 线性分类器

    这是2017年,斯坦福大学,李飞飞教授及其博士生讲授的CS231n课程的第二节,主要内容是KNN算法.距离度量算法.超参数的选择方法.线性分类器的简单介绍. 所有图像来自课程ppt:http://cs ...

  5. 【零基础】从零开始学神经网络《python神经网络编程》——手写数字识别实战

    文章目录 前言 一.机器学习是什么,深度学习是什么? 二.对NN,CNN,RNN,GNN,GAN的名词解释 三.详细介绍神经网络(NN) 1.认识神经网络 2.神经元 3.激活函数 4.权重--连接的 ...

  6. PyTorch基础入门五:PyTorch搭建多层全连接神经网络实现MNIST手写数字识别分类

    )全连接神经网络(FC) 全连接神经网络是一种最基本的神经网络结构,英文为Full Connection,所以一般简称FC. FC的准则很简单:神经网络中除输入层之外的每个节点都和上一层的所有节点有连 ...

  7. 机器学习基础 KNN(K近邻)算法及sklearn的基本使用(附带一些基础概念)

    文章目录 一. K-近邻算法简介 1. 什么是K-近邻算法 1.1 K-近邻算法(KNN)概念 1.2 电影类型分析 1.3 KNN算法流程总结 2. 小结 二.K近邻算法api初步使用 1. Sci ...

  8. 机器学习-监督学习之分类算法:K近邻法 (K-Nearest Neighbor,KNN)

    目录 KNN概述 举个例子: K值选取 距离计算 曼哈顿距离,切比雪夫距离关系(相互转化) k-近邻(KNN)算法步骤 相关代码实现 简单实例:判断电影类别 创建数据集 数据可视化 分类测试 运行结果 ...

  9. K近邻(k-Nearest Neighbor,KNN)算法,一种基于实例的学习方法

    1. 基于实例的学习算法 0x1:数据挖掘的一些相关知识脉络 本文是一篇介绍K近邻数据挖掘算法的文章,而所谓数据挖掘,就是讨论如何在数据中寻找模式的一门学科. 其实人类的科学技术发展的历史,就一直伴随 ...

最新文章

  1. NMHDR 与 NM_LISTVIEW,NM_TREEVIEW 的关系
  2. 电子电路基础复习 —— 三极管
  3. 最近在弄ionic3的时候遇到的一些问题(遇到就更新)
  4. mysql zf,mysql workbench建表时PK,NN,UQ,BIN,UN,ZF,AI的含义
  5. Keras Tutorial: Deep Learning in Python
  6. 对NumPy中dot()函数的理解(亲测,矩阵算法)
  7. Linux学习-15-学习LVM逻辑卷
  8. 致驱动工程师的一封信
  9. 数据结构c语言版堆排序,【数据结构】堆排序(C++实现)
  10. 归并排序(java实现)
  11. matlab程序框图,求大神告知程序框图
  12. Postgresql 配置远程访问
  13. python实现pdf合并
  14. JAVA毕业设计vue健康餐饮管理系统设计与实现计算机源码+lw文档+系统+调试部署+数据库
  15. TikTok跨境:TikTok搬运视频,怎么才不会识别出搬运?
  16. Caused by java.lang.Exception Failed to send data to Kafka Expiring
  17. BI项目实施为什么成功率那么低
  18. 【Linux】Shell脚本中如何使用“循环”遍历“数组”中的元素(包括MySQL的常用指令介绍)
  19. python_split()函数使用方法
  20. 以前写过的ajax基础案例(王欢-huanhuan)

热门文章

  1. 金蝶云苍穹笔记2022-07-13
  2. 组织结构图OrgChart.js
  3. 彻底聊聊关系数据库中的完整性约束:实体完整性、参照完整性和用户定义的完整性
  4. web前端日常更新 7.26
  5. 11g awr oracle 系列_Oracle 11g AWR 系列七:Active Sessi...-Oracle 11G新特性(共36个)-父子节点问题_169IT.COM...
  6. Python Turtle学习第一章:用Turtle画一些简单的图形
  7. Mproxy项目实录第2天
  8. 区块链巨头争相布局,区块链江湖暗流涌动
  9. Java:字符输入流、字符输出流
  10. 数据仓库——数据重刷机制