当给定数百个数组时,Sklearn PCA 返回一个只有一个值的数组
Posted
技术标签:
【中文标题】当给定数百个数组时,Sklearn PCA 返回一个只有一个值的数组【英文标题】:Sklearn PCA returning an array with only one value, when given an array of hundreds 【发布时间】:2016-12-03 03:05:34 【问题描述】:我编写了一个程序,旨在通过相似度对图像进行分类:
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 都应该有数百个值,而不仅仅是一个。我遵循的教程没有解释,文档只说transform和fit_transform都需要相同的数组格式。我应该如何处理这个问题?
【问题讨论】:
【参考方案1】:如果 n_components=2
,RandomizedPCA
最多只能保留 2 个组件(请参阅文档 here)。尝试增加它以允许选择更多组件;这应该可以解决您的问题。
【讨论】:
我只是把它改成了 10,然后是 12。两次都还是只有 1。 尝试使用显着更大的数字 - 你有 75000 个特征,所以 12 几乎没有。 我升至 250,而 X/Xy仍然只有一个值。我上升到 500 和 1000,我得到了MemoryError
。
另外,我的电脑在 250 时差点死机,没有响应。
尝试获取X
(print(X.shape)
) 的shape
属性。有时 numpy 数组不会像您期望的那样运行,并将它们的长度显示为不同的东西。【参考方案2】:
您对X = pca.fit_transform(iab)
和Xy = pca.transform(X)
所做的操作是错误的。
-
您正在丢失两个图像的
iab
变量。你需要
两个图像的扁平数组,在你的 for 循环之外。然而,
在您的第一次迭代之后,您的第二次迭代会覆盖 iab
数组。
即使您分别保存了两个数组,例如iab[0]
和iab[1]
,您也需要对这两个数组执行 PCA 并使用沿转换轴表示的两个图像。不过,您需要决定使用什么来学习转换。
这里是示例代码:
# 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 张显示“汽车”。训练模型后,您可以预测新图像是树还是汽车。
【讨论】:
别担心,我有数百张图片。我只是以这两个为例来看看脚本是否有效。 您能否详细介绍一下您的 PCA 拟合实际工作原理? 那么,你的意思是:iab 必须是一个 huge 数组,每张图片都是一条线?这似乎是方式,方式太大了。每张图片都转换为 750,000 个值。 @Rich,如果你没有存储太大的数组,那么你打算如何从所有图像中学习模式?按照您的方式,您读取图像并用下一张覆盖每次读取。 我鼓励您阅读我分享的关于 PCA 的链接,并找到其他更详细的资源。简而言之,在您的情况下,每张图像都有 750000 个特征(每个特征都是某个位置的像素)。您想要做的是将该维度减少到可管理的程度,例如 10 个功能(您选择 n_components=2)。 PCA 所做的是找到最能区分照片的 750000 个特征的线性组合。假设中心的 100 个像素是所有照片中差异最大的,它将选择第一个组件为 pixel_#5k + pixel_#5k1 + pixel#5k2... + pixel#5k100。以上是关于当给定数百个数组时,Sklearn PCA 返回一个只有一个值的数组的主要内容,如果未能解决你的问题,请参考以下文章
从 python 的 sklearn PCA 结果制作散点图
JSP的siom运作环境下sklearn进行辨别(PCA)代码实现的全过程