Я пытаюсь узнать о библиотеке дедупликации. Я пытаюсь сопоставить имена, которые совпадают более чем на 80%.
Делюсь кодом и ошибкой. Пожалуйста помоги
import dedupe
from Levenshtein import distance
def test():
# Sample data (replace with your actual library data)
data = [
{'name': 'Alice Smith', 'address': '123 Main St', 'phone': '555-1212'},
{'name': 'Alice SmIth', 'address': '123 Main Street', 'phone': '555-1213'},
{'name': 'Bob Johnson', 'address': '456 Elm St', 'phone': '555-3434'},
{'name': 'Charlie Brown', 'address': '789 Maple Ave', 'phone': '555-5656'},
]
# Define fields for comparison (adjust based on your data)
# Define data fields and comparison functions
fields = [
{'field': 'name', 'comparators': ['name_similarity']},
]
# Define similarity functions - customize based on your matching criteria
def name_similarity(s1, s2):
# Implement your name comparison logic here (e.g., Levenshtein distance, etc.)
distance1 = distance(s1, s2)
similarity = 1 - (distance1 / max(len(s1), len(s2))) # Normalize distance to 0-1 similarity
return similarity
# Set thresholds for field-wise and overall similarity (adjust as needed)
deduper = dedupe.Dedupe(fields)
deduper.threshold( threshold=0.8)
# Process the data for deduplication
deduped_data = deduper.dedupe(data)
# Print the deduplicated results
print("Deduplicated Data:")
for cluster in deduped_data:
print(cluster)
if __name__ == '__main__':
test()
.....
C:\PythonProject\pythonProject\venv\Graph_POC\Scripts\python.exe C:\PythonProject\pythonProject\matching.py Traceback (most recent call last): File "C:\PythonProject\pythonProject\venv\Graph_POC\Lib\site-packages\dedupe\datamodel.py", line 152, in typify_variables
variable_type = definition["type"]
~~~~~~~~~~^^^^^^^^ KeyError: 'type'
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "C:\PythonProject\pythonProject\matching.py", line 45, in <module>
test() File "C:\PythonProject\pythonProject\matching.py", line 32, in test
deduper = dedupe.Dedupe(fields)
^^^^^^^^^^^^^^^^^^^^^ File "C:\PythonProject\pythonProject\venv\Graph_POC\Lib\site-packages\dedupe\api.py", line 1155, in __init__
self.data_model = datamodel.DataModel(variable_definition)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\PythonProject\pythonProject\venv\Graph_POC\Lib\site-packages\dedupe\datamodel.py", line 42, in __init__
self.primary_variables, all_variables = typify_variables(variable_definitions)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\PythonProject\pythonProject\venv\Graph_POC\Lib\site-packages\dedupe\datamodel.py", line 161, in typify_variables
raise KeyError( KeyError: "Missing variable type: variable specifications are dictionaries that must include a type definition, ex. {'field' : 'Phone', type: 'String'}"
Process finished with exit code 1






Мой ответ — dedupe>=2.0, и код может не работать в других версиях библиотеки.
Также я бы посоветовал просмотреть эти руководства, в них много полезной информации: https://dedupeio.github.io/dedupe-examples/docs/csv_example.html
Вернемся к вашей ошибке: при инициализации класса dedupe.Dedupe он ожидает от вас передачи информации о типах полей (см. переменную fields в коде ниже).
Также ваши данные должны быть отформатированы немного по-другому: каждая строка должна иметь идентификатор. Проверьте переменную data_d в коде ниже.
Еще одна вещь, которой вам не хватает - список помеченных примеров. Обычно это несколько совпадающих пар и несколько различных пар (лучше иметь не менее 10 пар в каждой группе). Они сохраняются в переменной labeled_example в коде.
Наконец, если вы планируете использовать собственные компараторы, вам следует изменить field_type на Custom. В противном случае dedupe будет использовать стандартный компаратор на основе типа поля (Строка/Категория/С плавающей запятой и т. д.).
проверьте эту ссылку на наличие всех доступных определений переменных:
https://docs.dedupe.io/en/latest/Variable-definition.html
import dedupe
from Levenshtein import distance
# Define similarity functions - customize based on your matching criteria
def name_similarity(s1, s2):
# Implement your name comparison logic here (e.g., Levenshtein distance, etc.)
distance1 = distance(s1, s2)
similarity = 1 - (distance1 / max(len(s1), len(s2))) # Normalize distance to 0-1 similarity
return similarity
def test():
# Sample data (replace with your actual library data)
data = [
{'name': 'Alice Smith', 'address': '123 Main St', 'phone': '555-1212'},
{'name': 'Alice SmIth', 'address': '123 Main Street', 'phone': '555-1213'},
{'name': 'Bob Johnson', 'address': '456 Elm St', 'phone': '555-3434'},
{'name': 'Bob Johnson', 'address': '457 Elm St', 'phone': '555-3434'},
{'name': 'Charlie Brown', 'address': '789 Maple Ave', 'phone': '555-5656'},
{'name': 'Charlie Brown', 'address': '789 Meple Ave', 'phone': '555-5656'},
{'name': 'Karry Perry', 'address': '102 Meple Ave', 'phone': '555-3556'},
{'name': 'Karri Perry', 'address': '102 Meple Ave', 'phone': '555-3556'},
]
# give examples of matched Rows and distinct Rows
labeled_examples = {
"match": [(data[0], data[1]),
(data[2], data[3]),
(data[4], data[5])],
"distinct": [(data[0], data[2]),
(data[2], data[4]),
(data[4], data[6])],
}
data_d = {i:record for i, record in enumerate(data)}
# Define fields for comparison (adjust based on your data)
# Define data fields and comparison functions
fields = [
{'field': 'name', 'type': 'Custom', 'comparator': name_similarity},
# {'field': 'address', 'type': 'String'},
{'field': 'phone', 'type': 'String'},
]
deduper = dedupe.Dedupe(fields)
deduper.prepare_training(data_d)
deduper.mark_pairs(labeled_examples)
# # # !! This line required to run this example - very small dataset
# # # !! Remove it if your dataset have more than 10 examples in each class
# # # this is GridSearchCV.cv parameter for creating KFold
deduper.classifier.cv = 2
# # # train
_ = deduper.train()
clustered_dupes = deduper.partition(data_d, threshold=0.5)
print('# duplicate sets', len(clustered_dupes))
cluster_membership = {}
for cluster_id, (records, scores) in enumerate(clustered_dupes):
for record_id, score in zip(records, scores):
cluster_membership[record_id] = {
"Cluster ID": cluster_id,
"confidence_score": score
}
print(cluster_membership)
if __name__ == '__main__':
test()
выход:
{0: {'Cluster ID': 0, 'confidence_score': 0.82329434},
1: {'Cluster ID': 0, 'confidence_score': 0.82329434},
2: {'Cluster ID': 1, 'confidence_score': 0.96056044},
3: {'Cluster ID': 1, 'confidence_score': 0.96056044},
4: {'Cluster ID': 2, 'confidence_score': 0.96056044},
5: {'Cluster ID': 2, 'confidence_score': 0.96056044},
6: {'Cluster ID': 3, 'confidence_score': 0.9537174},
7: {'Cluster ID': 3, 'confidence_score': 0.9537174}}
Привет @Johnny Cheesecuter, спасибо за решение. Но будет ли это решение работать с реальными данными, где у меня 500 тысяч записей? и в этом случае мне нужно передать больше данных для обучения модели?
Честно говоря, сам этой библиотекой не пользовался. Чем больше у вас тренировочных данных — тем лучше. Поэтому по возможности предоставьте на тренировке все, что у вас есть. Но они просят минимум 10 записей совпадений и отличий. Я считаю, что библиотека не оптимизирована с точки зрения производительности/скорости обработки. К счастью, вам нужно запустить все один раз. И окончательные результаты кластеризации очень многообещающие.
Привет @johnny Cheesecutter. Я поделился одной проблемой, с которой столкнулся во время подготовки к тренировкам. Имеете ли вы какое-либо представление об этом? Было бы здорово . stackoverflow.com/questions/78325057/…
извини, какую версию дедупа ты используешь?