Postgresql中的均方根

5

我正在开发一个使用机器学习来预测图像相似度的图像复制库。在此过程中,我们使用均方根误差(Root Mean Square)计算两个图像之间的相似性(我不会进一步解释)。执行此功能的函数如下所示。

# Function that calulates the mean squared error (mse) between two image matrices
def _mse(imageA, imageB):
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])
    return err

我测试了包含5K张图片的文件夹,我的模型效果很好,但是耗时太长。因此,我决定重构代码并将所有张量存储在数据库中。为什么?

如果我将所有图像的张量存储在数据库中,然后使用它来查询即将到来的图像张量,我会很快得到结果。反复遍历所有图像+将一个图像RMS与其他图像匹配将导致许多组合,这需要时间。

解决方案

如果我将所有张量(列表或数组)存储在Postgres数据库中,那么我可以轻松地查询它们与RMS相关的内容,以一次性获取所有图像,而不是遍历它们并找出重复项。

我需要您的帮助来找出是否有任何方法可以查询Postgres以获得最接近RMS的图像

类似于以下内容:

SELECT ID_PARTNER, ID_ACCOUNT
  , SQRT(Avg( POWER(Act_F_1 - Pred_F_1 , 2) ) ) as feature_1_rmse
FROM ...
GROUP BY ID_PARTNER, ID_ACCOUNT

类似问题:如何在直接从表格获取数据时获取RMSE分数?编写查询以实现该目标

这是数据库的样子

这是数据库的样子


我对你想要做的事情感到困惑。Act_F_1和Pred_F_1的值从哪里来?在查询之间它们有多少次是相同的? - David Oldford
请访问:直接从表中获取数据时获取RMSE分数。为该链接编写一个查询以检查Act_F_1和Pred_F_1的来源...我正在尝试构建一个图像重复库..可以在这种情况下直接使用Postgres快速查找重复项。 - dotsinspace
1个回答

2
如果我正确理解您想要做的事情,您只需要创建一个列来保存RMSE计算结果,然后更新表格进行计算。
UPDATE table_name as orig set RMSE=(select SQRT(Avg( POWER(Act_F_1 - Pred_F_1 , 2) ) ) from table_name as copy where orig.ID_PARTNER=copy.ID_PARTNER and orig.ID_ACCOUNT=copy.ID_ACCOUNT GROUP BY ID_PARTNER, ID_ACCOUNT);

编辑:我之前没有注意到分组。我认为这个操作正确地创建了一个预计算的字段,但它可能非常低效,因为我相信它将为每个ID_PARTNER ID_ACCOUNT对重新计算。在SQL中可能有更好的方法来处理这个问题。我会先SELECT DISTINCT ID_PARTNER, ID_ACCOUNT from table_name然后在代码中运行它,并且对于我拥有的每个元组都会运行SELECT SQRT(Avg( POWER(Act_F_1 - Pred_F_1 , 2) ) ) from table_name where ID_PARTNER=? and ID_ACCOUNT=?,然后对于每个值update table_name set RMSE=?。另外,您可以创建一个仅包含ID_PARTNER、ID_ACCOUNT和RMSE的表,并一次性将结果放入其中。

然后数据库中的表将具有所有预计算的值,并且您可以在其上运行查询。如果要查找接近search_RMSE值的内容,请执行以下操作。

SELECT ...,ABS(RMSE - search_RMSE) as RMSE_DIFF from table_name order by RMSE_DIFF;

这并不一定是计算的超级优化方式。你提到了重复性,这意味着你正在寻找相同的值,但是你的计算是浮点数,因此你甚至可能得到应该是相同的值但最终却不是那样的值。你只关心最接近的值还是关心多个最接近的值?如果你只制作一个巨大的表格,并按RMSE排序,每行的最接近值将是上面或下面的行,最接近值的集合将只从该行向上和向下增长。
我不完全确定为什么你想在其中涉及数据库,除非你无法将所有数据放入内存中。如果是这种情况,你可以将原始数据放入数据库中,然后使用你所提到的带有order by子句的select语句,并将其存储在数据库外的块中(如果你需要)。
总之,有很多方法可以做到这一点,我个人会使用cython模块来避免Python中极慢的数学运算(它比numpy快得多,几乎与Python相同),并使用内存数据结构以及一些临时文件来完成所有这些操作。

谢谢您的回答。但问题是,我有大量的图像集合,这些图像将随着时间的推移而增加。这就是为什么我不能使用像Redis等缓存内存的原因。当涉及到存储RMS时,又出现了问题。因为我必须对数据库中的所有先前图像进行RMS计算。现在我不能放置原始数据,因为那样我必须获取所有数据并对其进行循环,这将再次变慢 :( - dotsinspace
你有多少条记录,数据字段具体是什么样子的,比如数据类型是什么?如果你可以计算所有值并按它们排序(你可以使用数据库来完成,并让它自动处理内存和存储),那么你可以快速找到相似的RMSE值。如果你不预先计算并排序,那么你就必须重新计算每个搜索。如果你获得新的记录,你可以使用插入排序。你仍然可以使用一个带有聪明字段的数据库来完成这个任务。我不是建议像REDIS这样的东西,而是建议在RAM中使用数据表。 - David Oldford
哦,你觉得在一定误差范围内搜索RMSE相似的图像这个想法可行吗?还是你需要找到最接近的x张图片?我的许多讨论都依赖于PostGres的查询优化器,如果你在RMSE值上建立索引并且你的查询要求不是问题,那么这些讨论可能就没有意义了。当然,如果你的库只是某人本地运行而不是一个Web服务,人们会对它进行持续需求,我认为你的问题可以很容易地解决,无需使用数据库或类似工具。 - David Oldford
首先,我有超过1个核心图像..现在如果用户上传了'x'图像,那么我使用CNN生成一个矩阵,然后我必须匹配该矩阵..现在排序或任何其他搜索算法都会失败。 - dotsinspace
哦,我明白了,我错过了GROUP BY子句。尽管这意味着每个唯一的ID_Partner和ID_ACCOUNT值对只有一个值,并且这些值仅在创建新的ID_Partner ID_ACCOUNT对时更改,所以您仍应该能够预先计算,在插入时更新某些值并使用值表查找相似的值。 - David Oldford
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接