编辑:
事实证明,Tf.keras.Model
当存在此类继承时,在继承树中继承的基类更高,可以观察到以下描述的行为。与普通脚本相比,普通Python类的性能可以忽略不计。
如果有可用的更新,我还没有找到有关此行为的任何相关文档。
编辑2:
我没有找到任何与此相关的文档(因此需要确认),但似乎:如果我将任何对象分配给self
(在Tf.keras.Model
继承的类中),则所有包含的对象都将tf.Variables
被提取并出现在trainable_variables
该类的属性中。因此,我的假设是keras.Model
检查所有self
想找到某些特定对象的self
任务,而这种检查会使庞大的dict任务变慢。
供参考:检查深入嵌套列表和字典,但不检查类,除非它们扩展ts.keras.Model
或tf.keras.Layer
原始问题:
我有一个col
字符串列表(〜30万行〜30个字符字符串,可以给您一个想法)。确切地说,这pandas.DataGrid
不是清单。
我正在创建一个查找字典以供将来使用,如下所示:
direct = {}
inverse = {}
# progressive
progressive = 0
# create direct map
for label in col:
# skip if present
if str(label) in direct:
continue
# else add to direct
direct[str(label)] = progressive
inverse[progressive] = str(label)
progressive += 1
没什么奇怪的,它需要0.15秒,并且python进程的内存使用是合理的。
然后,我将代码移到一个类中,这里的事情变得很奇怪。这里提供了同一功能的两个略有不同的版本。
版本A:
def fromDataset(self, column):
# reset map
self.direct = {}
self.inverse = {}
# progressive
progressive = 0
# create direct map
for label in column:
# skip if present
if str(label) in self.direct:
continue
# else add to direct
self.direct[str(label)] = progressive
self.inverse[progressive] = str(label)
progressive += 1
版本B:
def fromDataset(self, column):
# reset map
direct = {}
inverse = {}
# progressive
progressive = 0
# create direct map
for label in column:
# skip if present
if str(label) in direct:
continue
# else add to direct
direct[str(label)] = progressive
inverse[progressive] = str(label)
progressive += 1
self.direct = direct
self.inverse = inverse
所有建议的功能都产生相同的结果(约有120k条目的字典,RAM占用约30MB)
我可以接受的是,版本A的访问速度self
可能会比版本B慢,但是我无法理解的是,版本B耗时2.16秒(比以前多14倍)的天气,版本A甚至都无法进行测试(10点后) +分钟仍没有结果,进程内存使用量增加500+ MB)
更奇怪的是,版本B创建字典需要0.17秒,而执行字典需要2秒:
self.direct = direct
self.inverse = inverse
经过一整天的迷失之后,我开始想知道是否缺少与Python内存分配相关的东西。我想到的唯一有意义的假设是self.direct = direct
导致Python实际上在ram中移动/复制字典。
谁能解释我版本A和版本B中与纯脚本版本有何根本差异的情况?
我创建了一个可复制的示例,但没有遇到任何问题:
import random
import string
import pandas
def gen_random_word(word_length=30):
return ''.join((random.choice(string.ascii_letters) for _ in range(word_length)))
# I create a list of 300000 labels (but only 150k distinct labels) of 30 characters
labels = [gen_random_word() for _ in range(150000)]
labels = labels + labels
random.shuffle(labels)
# A dataframe here is useless but I try to get close to your own example
df = pandas.DataFrame(
{'labels': labels}
)
class A:
def __init__(self):
self.direct = {}
self.inverse = {}
self.progressive = 0
def fromDataset(self, column):
# create direct map
for label in column:
# skip if present
if str(label) in self.direct:
continue
# else add to direct
self.direct[str(label)] = self.progressive
self.inverse[self.progressive] = str(label)
self.progressive += 1
class B:
def __init__(self):
self.direct = {}
self.inverse = {}
self.progressive = 0
def fromDataset(self, column):
# reset map
direct = {}
inverse = {}
# progressive
progressive = 0
# create direct map
for label in column:
# skip if present
if str(label) in direct:
continue
# else add to direct
direct[str(label)] = progressive
inverse[progressive] = str(label)
progressive += 1
self.direct = direct
self.inverse = inverse
self.progressive = progressive
第一次测试:
%%time # remove that if you are not using jupyter and use another timing solution
direct = {}
inverse = {}
# progressive
progressive = 0
# create direct map
for label in df['labels']:
# skip if present
if str(label) in direct:
continue
# else add to direct
direct[str(label)] = progressive
inverse[progressive] = str(label)
progressive += 1
挂墙时间:267毫秒
第二次测试:
%%time
a = A()
a.fromDataset(df['labels'])
挂墙时间:249毫秒
第三次测试:
%%time
b = B()
b.fromDataset(df['labels'])
挂墙时间:220毫秒
所以...没什么大不了的。
您的繁殖是正确的。我已经从类中删除了所有内容(我的意思是其他函数,甚至是anchestor类),现在执行正常。通过测试每个超级类,我在项目中发现了一个继承Tf.keras.Model的类-keras模型是否有可能修改非@tf函数上的内存管理?(当我再次继承它时,行为将变为我所描述的)
当然,tf.keras.Model可以做很多事情来影响内存和执行时间。
如果您对此有所了解,我希望您能更新您的答案,谢谢。