总结自
https://www.cnblogs.com/1832921tongjieducn/p/10779099.html
https://www.cnblogs.com/1832921tongjieducn/p/10779807.html
https://blog.youkuaiyun.com/sinat_26917383/article/details/72857454
先看python的迭代器
迭代器是一种不依赖索引的迭代取值方式。
可迭代对象:在python中,内置有iter方法的数据类型或者对象都是可迭代对象,执行可迭代对象iter方法得到的返回值就是一个迭代器对象。
迭代器对象是内置有next方法的。迭代器对象也内置有iter方法,执行该方法得到的仍然是迭代器本身。
对迭代器对象print,得到是迭代器的地址。对迭代器使用next方法,可以不依赖索引访问可迭代对象里面每一个值。
列表、字典、字符串都是可迭代对象。
a=[1,2,3,4,5,6,7]
#a='wearetheonlyone'
#a={'a':1,'b':2,'c':3,'d':4,'e':5}#字典在存储时是乱序的,迭代器访问也是乱序的
l=iter(a)
print(l)
print(next(l))
print(next(l))
print(next(l))
print(next(l))
运行结果
<listiterator object at 0x3885ad0>
1
2
3
4
for循环的底层运行机制:for循环可以称之为迭代器循环,其底层运行机制用的就是迭代器。
for k in dic:
print(k)
1.先调用in 后面那个对象的iter方法,得到该可迭代的对象的迭代器对象
2.执行迭代器对象的next方法,将得到的返回值赋值给in 前面的变量名,然后执行一次循环体代码
3.循环往复,直到取干净迭代器内所有的值,自动捕捉异常结束循环
总结迭代器的优缺点:
优点:
1,提供了一种不依赖索引的迭代取值方式
2,节省内存
缺点:
1,只能往后取,不能往前取,而且是一次性的,值取干净之后无法再取值,除非重新得到新的迭代器对象,不如按索引取值的方式灵活
2,无法预知迭代器的长度
3,在迭代过程中对迭代对象进行修改有可能会破坏迭代过程,应该避免
现在我们使用的都是官方内部定义还的迭代器,在今后中,如果我们需要用到比较大的数据,可以用一个自定义的迭代器来实现,而不是用列表或者文件字典等实现,这样更加节省内存。
可以使用生成器自定义迭代器:
函数内但凡有一个yield关键字,再调用函数就不会执行函数代码,得到的返回值就是一个生成器对象。
生成器本身就是一种迭代器,对其使用next()方法会触发生成器所对应的函数的执行,直到遇到yield才停下来,然后把yield的返回值当做本次next操作的返回值。
def func():
print('first')
yield 1
print('second')
yield 2
print('third')
yield 3
l=func()
while True:
try:
print(next(l))
except:
break
fit_generator
运行结果:
first
1
second
2
third
3
生成器的迭代器g的内置函数还有send():
g.send()的作用和next的作用相类似,都是返回到上一次生成器函数执行的位置,也就是上一次yield的位置,开始执行这个生成器函数,但是在执行生成器函数之前,会先把send()括号后面的参数传递给yeild,然后再开始执行生成器函数,直到遇到下一个yeild停止或者整个生成器函数结束。
def dog(name):
print('狗哥%s准备开吃' %name)
while True:
food = yield
print('狗哥%s吃了%s' %(name,food))
g = dog('alex')
next(g) #初始化
g.send('骨头')
g.send('剩饭')
执行结果:
狗哥alex准备开吃
狗哥alex吃了骨头
狗哥alex吃了干水
注意:g.send(None) 完全等同于next(g)。强调:对于表达式形式yeild
的生成器在使用前必须先用next(g)或者g.send(None)初始化一次
fit_generator函数就是使用了python的生成器,逐个生成数据的batch并进行训练。
#利用Python的生成器,逐个生成数据的batch并进行训练。
#生成器与模型将并行执行以提高效率。
#例如,该函数允许我们在CPU上进行实时的数据提升,同时在GPU上进行模型训练
#参考链接:http://keras-cn.readthedocs.io/en/latest/models/sequential/
有了该函数,图像分类训练任务变得很简单。
fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)
# 案例:
def generate_arrays_from_file(path):
while 1:
f = open(path)
for line in f:
# create Numpy arrays of input data
# and labels, from each line in the file
x, y = process_line(line)
yield (x, y)
f.close()
model.fit_generator(generate_arrays_from_file('/my_file.txt'),
samples_per_epoch=10000, epochs=10)
注意:这里generate函数必须要使用yield()函数。
yield函数的作用可以看作是:每次程序执行到yield后,将yield的参数返回,
之后程序继续执行,每次执行到yield将参数内容返回即可。
当训练模型的时候,逐次生成所需要训练的数据batch,并将其使用yield返回
使用带有yield的generate函数,配合fit_generate(),逐个生成数据的
batch并进行训练,当训练数据过大时,可以防止内容溢出爆栈
其他的两个辅助的内容:
evaluate_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False)
predict_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False, verbose=0)
evaluate_generator:本函数使用一个生成器作为数据源评估模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。
predcit_generator:本函数使用一个生成器作为数据源预测模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。