温馨提示:本文翻译自stackoverflow.com,查看原文请点击:python - Tf.keras.Model class ~ self variables performance
dictionary python tensorflow2.0

python - Tf.keras.Model类〜自变量性能

发布于 2020-04-07 10:55:18

编辑:

事实证明,Tf.keras.Model当存在此类继承,在继承树中继承的基类更高,可以观察到以下描述的行为。与普通脚本相比,普通Python类的性能可以忽略不计。

如果有可用的更新,我还没有找到有关此行为的任何相关文档。

编辑2:

我没有找到任何与此相关的文档(因此需要确认),但似乎:如果我将任何对象分配给self(在Tf.keras.Model继承的类中),则所有包含的对象都将tf.Variables被提取并出现在trainable_variables该类属性中。因此,我的假设是keras.Model检查所有self想找到某些特定对象的self任务,而这种检查会使庞大的dict任务变慢。

供参考:检查深入嵌套列表和字典,但不检查类,除非它们扩展ts.keras.Modeltf.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中与纯脚本版本有何根本差异的情况?

查看更多

提问者
Newbie
被浏览
23
Corentin Limier 2020-01-31 23:48

我创建了一个可复制的示例,但没有遇到任何问题:

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毫秒

所以...没什么大不了的。