金融行业网站建设方案,咸阳万企网站建设,兰州小程序定制开发,wordpress nginx 重写规则原理
线性数据分割 如下图所示#xff0c;其中含有两类数据#xff0c;红的和蓝的。如果是使用kNN算法#xff0c;对于一个测试数据我们要测量它到每一个样本的距离#xff0c;从而根据最近的邻居分类。测量所有的距离需要足够的时间#xff0c;并且需要大量的内存存储训…原理
线性数据分割 如下图所示其中含有两类数据红的和蓝的。如果是使用kNN算法对于一个测试数据我们要测量它到每一个样本的距离从而根据最近的邻居分类。测量所有的距离需要足够的时间并且需要大量的内存存储训练样本。但是分类下图所示的数据真的需要占用这么多资源吗 我们在考虑另外一个想法。我们找到了一条直线f (x) ax1 bx2 c它可以将所有的数据分割到两个区域。当我们拿到一个测试数据X 时我们只需要把它代入f (x)。如果|f (X) | 0它就属于蓝色组否则就属于红色组。我们把这条线称为决定边界(Decision_Boundary)。很简单而且内存使用效率也很高。这种使用一条直线(或者是高位空间中的超平面将平面上的数据分成两组的方法成为线性分割。 从上图中我们看到有很多条直线可以将数据分为蓝红两组哪一条直线是最好的呢直觉上上这两条直线应该是与两组数据的距离越远越好。为什么呢因为测试数据可能有噪音影响(真实数据 噪声)。这些数据不应该影响分类的准确性。所以这条距离远的直线抗噪声能力也就最强。所以SVM 要做就是找到一条直线并使这条直线到训练样本各组数据的最短距离最大。下图 中加粗的直线经过中心。 要找到决定边界就需要使用训练数据。我们需要所有的训练数据吗不是的只需要那些靠近边界的数据如上图中一个蓝色的圆盘和两个红色的方块。我们叫他们支持向量经过他们的直线叫做支持平面。有了这些数据就可以找到决定边界了。 实际上我们还是会担心所有的数据因为这对于数据简化有帮助。 到底发生了什么呢首先我们找到了分别代表两组数据的超平面。例如蓝色数据可以用ωT xb0 1 表示而红色数据可以用ωT xb0 −1 表示ω 叫做权重向量ω [ω1, ω2, . . . , ω3],x 为特征向量x [x1, x2, . . . ,xn]b0 被叫做bias(截距)。权重向量决定了决定边界的走向而bias 点决定了它(决定边界的位置。决定边界被定义为这两个超平面的中间线(平面),表达式为ωT xb0 0。 非线性数据分割 想象一下如果一组数据不能被一条直线分为两组怎么办例如在一维空间中X 类包含的数据点有(-3,3O 类包含的数据点有-1,1。很明显不可能使用线性分割将X 和O 分开。但是有一个方法可以帮我们解决这个问题。使用函数 对这组数据进行映射后得到的X 为9O 为1这时就可以使用线性分割了。 或者我们也可以把一维数据转换成两维数据。我们可以使用函数对数据进行映射。这样X 就变成了(-3,9)和(3,9)而O 就变成了(-1,1)和(1,1)。同样可以线性分割,简单来说就是在低维空间不能线性分割的数据在高维空间很有可能可以线性分割。 通常我们可以将d 维数据映射到D 维数据来检测是否可以线性分割(Dd)。这种想法可以帮助我们通过对低维输入(特征)空间的计算来获得高维空间的点积。我们可以用下面的例子说明。 这说明三维空间中的内积可以通过计算二维空间中内积的平方来获得。这可以扩展到更高维的空间。所以根据低维的数据来计算算它们的高维特征。在进行完映射后我们就得到了一个高维空间数据。 除了上面的这些概念之外还有一个问题需要解决那就是分类错误。仅仅找到具有最大边缘的决定边界是不够的。我们还需要考虑错误分类带来的误差。有时我们找到的决定边界的边缘可能不是最大的但是错误分类是最少的。所以我们需要对我们的模型进行修正来找到一个更好的决定边界:最大的边缘最小的错误分类。评判标准就被修改为 下图显示这个概念。对于训练数据的每一个样本又增加了一个参数ξi。它表示训练样本到他们所属类(实际所属类)的超平面的距离。对于那些分类正确的样本个参数为0因为它们会落在它们的支持平面上。 参数C 的取值应该如何选择呢很明显应该取决于你的训练数据。虽然没有一个统一的答案但是在选取C 的取值时我们还是应该考虑一下下面的规则
如果C 的取值比较大错误分类会减少但是边缘也会减小。其实就是错误分类的代价比较高惩罚比较大。通常在数据噪声很小时我们可以选取较大的C 值。如果C 的取值比较小边缘会比较大但错误分类的数量会升高。其实就是错误分类的代价比较低惩罚很小。整个优化过程就是为了找到一个具有最大边缘的超平面对数据进行分类。如果数据噪声比较大时应该考虑这么做。
使用SVM 进行手写数据OCR 这里我们还是要进行手写数据的OCR但这次我们使用的是SVM 而不是kNN。在kNN 中我们直接使用像素的灰度值作为特征向量。这次我们要使用方向梯度直方图(Histogram of Oriented Gradients) HOG作为特征向量。在计算HOG 前我们使用图片的二阶矩对其进行抗扭斜(deskew)处理。所以我们首先定义一个函数deskew()它可以对一个图像进行抗扭斜处理。下面就是deskew() 函数:
def deskew(img):m cv2.moments(img)if abs(m[mu02]) 1e-2:return img.copy()skew m[mu11]/m[mu02]M np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])img cv2.warpAffine(img,M,(SZ, SZ),flagsaffine_flags)return img 下图显示了对含有数字0 的图片进行抗扭斜处理后的效果。左侧是原始图像右侧是处理后的结果。 接下来我们要计算图像的HOG 描述符创建一个函数hog()。为此我们创建算图像X 方向和Y 方向的Sobel 导数。然后计算得到每个像素的梯度的方向和大小。把这个梯度转换成16 位的整数。将图像分为4 个小的方块对每一个小方块计算它们的朝向直方图(16 个bin),使用梯度的大小做权重。这样每一个小方块都会得到一个含有16 个成员的向量。4 个小方块的4 个向量就组成了这个图像的特征向量包含64 个成员。这就是我们要训练练数据的特征向量。
def hog(img):gx cv2.Sobel(img, cv2.CV_32F, 1, 0)gy cv2.Sobel(img, cv2.CV_32F, 0, 1)mag, ang cv2.cartToPolar(gx, gy)bins np.int32(bin_n*ang/(2*np.pi)) # quantizing binvalues in (0...16)bin_cells bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]mag_cells mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]hists [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]hist np.hstack(hists) # hist is a 64 bit vectorreturn hist 最后和前面一样我们将大图分割成小图。使用每个数字的前250 个作为训练数据后250 个作为测试数据。全部代码如下所示
# -*- coding: utf-8 -*-import cv2
import numpy as npSZ20
bin_n 16 # Number of bins
svm_params dict( kernel_type cv2.SVM_LINEAR,svm_type cv2.SVM_C_SVC,C2.67, gamma5.383 )
affine_flags cv2.WARP_INVERSE_MAP|cv2.INTER_LINEARdef deskew(img):m cv2.moments(img)if abs(m[mu02]) 1e-2:return img.copy()skew m[mu11]/m[mu02]M np.float32([[1, skew, -0.5*SZ*skew], [0, 1, 0]])img cv2.warpAffine(img,M,(SZ, SZ),flagsaffine_flags)return img
def hog(img):gx cv2.Sobel(img, cv2.CV_32F, 1, 0)gy cv2.Sobel(img, cv2.CV_32F, 0, 1)mag, ang cv2.cartToPolar(gx, gy)bins np.int32(bin_n*ang/(2*np.pi)) # quantizing binvalues in (0...16)bin_cells bins[:10,:10], bins[10:,:10], bins[:10,10:], bins[10:,10:]mag_cells mag[:10,:10], mag[10:,:10], mag[:10,10:], mag[10:,10:]hists [np.bincount(b.ravel(), m.ravel(), bin_n) for b, m in zip(bin_cells, mag_cells)]hist np.hstack(hists) # hist is a 64 bit vector
return histimg cv2.imread(digits.png,0)
cells [np.hsplit(row,100) for row in np.vsplit(img,50)]# First half is trainData, remaining is testData
train_cells [ i[:50] for i in cells ]
test_cells [ i[50:] for i in cells]###### Now training ########################
deskewed [map(deskew,row) for row in train_cells]
hogdata [map(hog,row) for row in deskewed]
trainData np.float32(hogdata).reshape(-1,64)
responses np.float32(np.repeat(np.arange(10),250)[:,np.newaxis])
svm cv2.SVM()
svm.train(trainData,responses, paramssvm_params)
svm.save(svm_data.dat)###### Now testing ########################
deskewed [map(deskew,row) for row in test_cells]
hogdata [map(hog,row) for row in deskewed]
testData np.float32(hogdata).reshape(-1,bin_n*4)
result svm.predict_all(testData)####### Check Accuracy ########################
mask resultresponses
correct np.count_nonzero(mask)
print (correct*100.0/result.size) 准确率达到了94%。你可以尝试一下不同的参数值看看能不能得到更高的准确率。或者也可以详细读一下这个领域的文章并用代码实现它。