当给定数百个

时间:2016-07-28 15:49:03

标签: python numpy scikit-learn transform pca

我写了一个程序,旨在通过相似性对图像进行分类:

for i in g:
    fulFi = i

    tiva = []
    tivb = []

    a = cv2.imread(i)
    b = cv2.resize(a, (500, 500))

    img2 = flatten_image(b)
    tivb.append(img2)
    cb = np.array(tivb)
    iab = trueArray(cb)

    print "Image:                      " + (str(i)).split("/")[-1]
    print "Image Size                  " + str(len(iab))
    print "Image Data:                 " + str(iab) + "\n"



pca = RandomizedPCA(n_components=2)
X = pca.fit_transform(iab)
Xy = pca.transform(X)

knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X, Xy.ravel())

def aip(img):
    a = cv2.imread(img)
    b = cv2.resize(a, (500, 500))

    tivb = []

    r = flatten_image(b)
    tivb.append(r)
    o = np.array(tivb)
    l = trueArray(o)

    print "Test Image:                 " + (str(img)).split("/")[-1]
    print "Test Image Size             " + str(len(l))
    print "Test Image Data:            " + str(l) + "\n"

    return l


testIm = aip(sys.argv[2])
b = pca.fit_transform(testIm)
print         "KNN Prediction:             " + str(knn.predict(b))

虽然完美地运行,但它有一个错误:无论使用何种图像,它都给了我完全相同的值:

Image:                      150119131035-green-bay-seattle-nfl-1024x576.jpg
Image Size                  750000
Image Data:                 [255 242 242 ..., 148 204 191]

Test Image:                 agun.jpg
Test Image Size             750000
Test Image Data:            [216 255 253 ..., 205 225 242]

KNN Prediction:             [-255.]

Image:                      150119131035-green-bay-seattle-nfl-1024x576.jpg
Image Size                  750000
Image Data:                 [255 242 242 ..., 148 204 191]

Test Image:                 bliss.jpg
Test Image Size             750000
Test Image Data:            [243 240 232 ...,  13  69  48]

KNN Prediction:             [-255.]

无论使用何种图像,KNN预测始终为255。经过进一步的调查,A发现问题出在我的PCA上:出于某种原因,它采用了一个包含750000值的数组并返回一个只有一个数组的数组:

pca = RandomizedPCA(n_components=2)
X = pca.fit_transform(iab)
Xy = pca.transform(X)

print "Iab:                        " + str(iab)
print "Iab Type:                   " + str(type(iab))
print "Iab length:                 " + str(len(iab))



print "X Type:                     " + str(type(X))
print "X length:                   " + str(len(X))
print "X:                          " + str(X)


print "Xy Type:                    " + str(type(Xy))
print "Xy Length:                  " + str(len(X))
print "Xy:                         " + str(Xy)

给出了这个:

Image:                      150119131035-green-bay-seattle-nfl-1024x576.jpg
Image Size                  750000
Image Data:                 [255 242 242 ..., 148 204 191]

Iab:                        [255 242 242 ..., 148 204 191]
Iab Type:                   <type 'numpy.ndarray'>
Iab length:                 750000
X Type:                     <type 'numpy.ndarray'>
X length:                   1
X:                          [[ 0.]]
Xy Type:                    <type 'numpy.ndarray'>
Xy Length:                  1
Xy:                         [[-255.]]

我的问题是为什么? X和Xy都应该有数百个值,而不仅仅是一个。我所遵循的教程没有解释,文档只说变换和fit_transform需要相同的数组格式。我该怎么接近这个?

2 个答案:

答案 0 :(得分:2)

如果n_components=2RandomizedPCA最多只会保留2个组件(请参阅文档here)。尝试增加此项以允许选择更多组件;这应该可以解决你的问题。

答案 1 :(得分:1)

您使用X = pca.fit_transform(iab)Xy = pca.transform(X)所做的事情是错误的。

  1. 您丢失了两张图片的iab变量。你需要的 在for循环之外,展平了两个图像的数组。然而, 在第一次迭代后,第二次迭代将覆盖iab 阵列。
  2. 即使您单独保存了两个数组,如iab[0]iab[1],您也需要在两者上执行PCA并使用沿变换轴表示的两个图像。您需要决定使用什么来学习转换。
  3. 以下是示例代码:

    # First initialize the PCA with desired components 
    pca = RandomizedPCA(n_components=2)
    
    # Next you need to fit data to learn the transformations
    pca.fit(np.vstack(iab[0].shape(1, len(iab[0]), iab[1].shape(1, len(iab[1])))
    
    # Finally you apply this learned transformation on input data
    X[0] = pca.transform(iab[0])
    X[1] = pca.transform(iab[1])
    

    你基本上在矩阵上学习PCA。行代表每个图像。您想要做的是尝试识别图像中哪些像素最能描述图像。为此,您需要输入许多图像,并找出哪些像素比其他图像更好地区分它们。在您使用拟合的方式中,您只需在一维列表中输入100个值,这实际上意味着,您有一个代表每个图像的值,并且您有100个图像。

    同样在您的情况下,如果只了解它所代表的内容,则将fit()transform()合并为一个有效的用例。无论如何,你错过了第二张图像的转换。

    如果您想了解有关PCA如何运作的更多信息,请阅读此answer

    最后,您无法在1个训练样本和1个测试样本上学习KNN分类器!学习算法旨在从一大堆输入中学习。

    你似乎需要的只是两者之间的基本距离。您需要选择距离指标。如果你选择使用欧几里德距离(也称为L2范数),那么这里是代码:

    dist = numpy.linalg.norm(X[0]-X[1])
    

    您也可以这样做:

    from scipy.spatial import distance
    dist = distance.euclidean(X[0], X[1])
    

    在任何情况下,再次转换转换后的数据没有任何意义,就像使用Xy = pca.transform(X)一样。这不会给你一个目标。

    当您说出100张图像时,您只能应用KNN等分类,其中50表示“树”,其余50表示“汽车”。训练模型后,您可以预测新图像是树还是汽车。