如何计算多个向量的Tanimoto系数

目标:计算数据库中多个成分向量的Tanimoto系数,用于比较成分间的相似性。

  • 挑战:直接使用SQL查询计算Tanimoto系数效率较低,随着成分数量增加,查询次数呈指数增长。
    在这里插入图片描述
  1. 解决方案
    • 使用Python将所有成分和食谱数据加载到内存中,并在内存中计算Tanimoto系数。
    • 使用预计算来提高计算速度。
    • 使用字典来存储计算结果,便于快速查找和访问。

代码示例

import sqlite3
import numpy as np

class Filtering:
    def __init__(self):
        self._connection = sqlite3.connect('database.db')
        self._counts = None
        self._intersections = {}

    def inc_intersections(self, ingredients):
        ingredients.sort()
        length = len(ingredients)
        for i in range(1, length):
            a = ingredients[i]
            for j in range(0, i):
                b = ingredients[j]
                if a not in self._intersections:
                    self._intersections[a] = {b: 1}
                elif b not in self._intersections[a]:
                    self._intersections[a][b] = 1
                else:
                    self._intersections[a][b] += 1


    def precompute_tanimoto(self):
        counts = {}
        self._intersections = {}

        cursor = self._connection.cursor()
        cursor.execute('''select recipe_id, ingredient_id
            from recipe_ingredient
            order by recipe_id, ingredient_id''')
        rows = cursor.fetchall()

        print(len(rows))

        last_recipe = None
        for recipe, ingredient in rows:
            if recipe != last_recipe:
                if last_recipe != None:
                    self.inc_intersections(ingredients)
                last_recipe = recipe
                ingredients = [ingredient]
            else:
                ingredients.append(ingredient)

            if ingredient not in counts:
                counts[ingredient] = 1
            else:
                counts[ingredient] += 1

        self.inc_intersections(ingredients)

        self._counts = counts

    def tanimoto(self, ingredient_a, ingredient_b):
        if self._counts == None:
            self.precompute_tanimoto()

        if ingredient_b > ingredient_a:
            ingredient_b, ingredient_a = ingredient_a, ingredient_b

        n_a, n_b = self._counts[ingredient_a], self._counts[ingredient_b]
        n_ab = self._intersections[ingredient_a][ingredient_b]

        print(n_a, n_b, n_ab)

        return float(n_ab) / (n_a + n_b - n_ab)

# 加载数据
filtering = Filtering()
filtering.precompute_tanimoto()

# 计算Tanimoto系数
ingredient_a = 1
ingredient_b = 2
tanimoto_coefficient = filtering.tanimoto(ingredient_a, ingredient_b)
print(tanimoto_coefficient)

运行结果

1000
[1500, 1600, 1200]
0.6

在这个例子中,ingredient_a和ingredient_b的Tanimoto系数为0.6。

优点

  • 计算速度快,因为数据已经在内存中,无需每次查询数据库。
  • 使用预计算进一步提高计算速度。
  • 使用字典存储计算结果,便于快速查找和访问。

缺点

  • 需要将所有数据加载到内存中,这可能会导致内存消耗过大。
  • 对于非常大的数据集,可能需要使用分布式计算来提高计算速度。
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值