Это проблема очистки данных.Чтобы использовать генеративный ИИ, вам нужны чистые непредвзятые данные.У меня есть десять тысяч миди-монофонических миди-файлов в одном каталоге, которые выскребаны из Интернета и несут чепуху для имен.Мне нужно идентифицировать похожие, но не идентичные песни (возможно, одну и ту же песню, но стилистически отличающиеся), которые смещают музыкальный генератор путем их дублирования. Поэтому я заменяю все ключевые сигналы на C, а все инструменты на пианино и т. Д. Теперь каждый midi-файлпросто серия последовательностей "note on" и "note off".таким образом, песни с сильным сходством, даже если они воспроизводятся в разных стилях, дают высокий коэффициент SequenceMatcher (difflib).Я сделал некоторый код, и он работает.но это невероятно медленно.Мне бы хотелось либо улучшить подход к открытию и закрытию файлов (возможно, с использованием словаря или двух), либо использовать многопроцессорность, но я не уверен, что делать дальше.
Я использовал рекурсивный подход и испортил двоичное сравнение, но этоПодход, как и md5sum, предназначен для сопоставления идентичных файлов.Я остановился на прогулке по каталогу и чтении в чанке, а затем во вложенном цикле, повторном просмотре каталога и чтении в чанке того же размера из другого файла в каталоге.а затем с помощью коэффициента SequenceMatcher, чтобы получить основу для сравнения.Я провел некоторое тестирование и определил размер фрагмента около 600 работ, чтобы идентифицировать подобную песню, когда установил сходство на что-то более девяноста процентов (см. Мой код).Но это все еще очень медленно, и я уверен, что есть лучший путь.Я усердно смотрел на многопоточность Параллельное сопоставление файлов, Python , но я не уверен в себе в этой области, и поскольку файлы находятся в одном каталоге, разве не стоит рассматривать тупик?Мне бы очень понравился вклад кого-то, кто знает их многопоточность и / или оптимизацию алгоритмов.
import sys
import os
import hashlib
from difflib import SequenceMatcher
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
count=0
for dirName, subdirs, fileList in os.walk('path to my directory'):
print('Scanning %s...' % dirName)
for filename in fileList:
path = os.path.join(dirName, filename)
in_file = open(path, 'rb') # Provide a path to disk or ISO image
data = in_file.read(600)
in_file.close()
for filename2 in fileList:
path = os.path.join(dirName, filename2)
in_file2 = open(path, 'rb')
data2 = in_file2.read(600)
in_file2.close()
if filename==filename2:
pass
else:
s=similar(data,data2)
if s>0.9:
print(filename +filename2+" "+str(s))
Я запустил это за разумное время в каталоге из примерно 1000 файлов (два часа или около того), и это сработало!но в каталоге из 10000 файлов он работал, ну, он работал слишком долго.
ОБНОВЛЕНИЕ : вот где я сейчас с кодом:
import multiprocessing
import sys
import os
import hashlib
from difflib import SequenceMatcher
import itertools
import string
import multiprocessing
def similar(a, b):
return SequenceMatcher(None, a, b).ratio()
min=4
l=[]
count=0
for dirName, subdirs, fileList in os.walk('/home/dedalous/tensorflow/Music_RNN_RBM/Pop_Music_Midi/'):
print('Scanning %s...' % dirName)
for filename in fileList:
path = os.path.join(dirName, filename)
in_file = open(path, 'rb')
s=in_file.read(800)
in_file.close()
l.append(s)
def get_filecontents(a,b):
print("**********************************************************************")
result=""
for c in a:
if c in string.printable:
result+=c
continue
if len(result) >= min :
print(result+" ")
result=""
if len(result) >= min: # catch result at EOF
print(result+" ")
for c in b:
if c in string.printable:
result+=c
continue
if len(result) >= min :
print(result+" ")
result=""
if len(result) >= min: # catch result at EOF
print(result+" ")
print("**********************************************************************")
def enum_tasks():
for a, b in itertools.combinations(l, 2):
yield (a,b)
def comparison(ab):
a,b = ab
return (similar(a, b),a,b)
if __name__ == '__main__':
CHUNK_SIZE = multiprocessing.cpu_count()
pool = multiprocessing.Pool()
for result in pool.imap(comparison, enum_tasks(), CHUNK_SIZE):
if result[0]>.9:
get_filecontents(result[1],result[2])
print(result[0])
Я запускаю несколько тестов, чтобы проверить, работает ли это быстрее (должно быть, все четыре процессора работают на 100%. Надеюсь, я правильно понял метод enum_tasks ....