优化目录中具有相似但不相同内容的文件的比较顺序,以便进行重复数据删除

时间:2019-05-27 19:52:06

标签: python-2.7 recursion optimization multiprocessing difflib

它是数据清理问题。要使用生成AI,您需要干净无偏的数据。我在一个目录中有一万个Midi单音midi文件,这些文件是从网络上抓取的,而且对名称毫无意义。我需要识别相似但不完全相同的歌曲(也许是同一首歌曲,但在风格上有所不同),这会因音乐的复制而使音乐生成器产生偏差。因此,我将所有关键信号更改为C,将所有乐器更改为钢琴等。只是一系列“ note on”“ note off”序列。因此,即使以不同风格播放,具有高度相似性的歌曲也会产生较高的SequenceMatcher(difflib)比率。我做了一些代码,它可以工作。但它的速度非常慢。我很乐意改善打开和关闭文件的方式(也许使用一两个字典)或使用多处理,但是我不确定如何进行。

我已经使用了递归方法,并且搞乱了二进制比较,但是这种方法(例如md5sum)用于匹配相同的文件。我决定遍历目录并读取大块,然后在嵌套循环中再次遍历目录,并从目录中的另一个文件中读取相同大小的块。然后使用SequenceMatcher比率获得比较的基础。当我将相似度设置为百分之九十以上时,我进行了一些测试,并用大约600块的块大小来识别相似的歌曲(请参阅我的代码)。但是它仍然很慢,我相信有更好的方法。我一直在努力研究多线程Parallel file matching, 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方法。...

0 个答案:

没有答案