你实际上已经击中了非常有趣的现象在联邦学习中。特别是,这里需要问的问题是:训练指标是如何计算的?
通常计算训练指标在当地培训期间;因此,它们是在客户端拟合其本地数据时计算的;在 TFF 中,它们是在执行每个局部步骤之前计算的——这种情况发生here https://github.com/tensorflow/federated/blob/master/tensorflow_federated/python/learning/keras_utils.py#L465在前向传递呼叫期间。如果您想象极端情况,其中指标仅在end对每个客户进行一轮培训后,您会清楚地看到一件事——客户正在报告代表的指标它与他的本地数据的吻合程度如何.
然而,联邦学习必须在每轮训练结束时生成一个单一的全局模型——在联邦平均中,这些局部模型是在参数空间中一起平均。在一般情况下,尚不清楚如何直观地解释这样的步骤 - 参数空间中非线性模型的平均值不会为您提供平均预测或类似的结果。
联合评估采用这个平均模型,并对每个客户端运行本地评估,根本不拟合本地数据。因此,如果您的客户端数据集具有截然不同的分布,则您应该预期从联合评估返回的指标与从一轮联合训练返回的指标有很大不同 - 联合平均正在报告收集的指标适应本地数据的过程中,而联合评估正在报告收集的指标将所有这些本地训练的模型平均后.
事实上,如果您交错调用next
迭代过程和评估函数的函数,您将看到如下模式:
train metrics=<mean_squared_error=88.22489929199219,loss=88.6319351196289>
eval metrics=<mean_squared_error=33.69473648071289,loss=33.55160140991211>
train metrics=<mean_squared_error=8.873666763305664,loss=8.882776260375977>
eval metrics=<mean_squared_error=29.235883712768555,loss=29.13833236694336>
train metrics=<mean_squared_error=7.932246208190918,loss=7.918393611907959>
eval metrics=<mean_squared_error=27.9038028717041,loss=27.866817474365234>
train metrics=<mean_squared_error=7.573018550872803,loss=7.576478958129883>
eval metrics=<mean_squared_error=27.600923538208008,loss=27.561887741088867>
train metrics=<mean_squared_error=7.228050708770752,loss=7.224897861480713>
eval metrics=<mean_squared_error=27.46322250366211,loss=27.36537742614746>
train metrics=<mean_squared_error=7.049572944641113,loss=7.03688907623291>
eval metrics=<mean_squared_error=26.755760192871094,loss=26.719152450561523>
train metrics=<mean_squared_error=6.983217716217041,loss=6.954374313354492>
eval metrics=<mean_squared_error=26.756895065307617,loss=26.647253036499023>
train metrics=<mean_squared_error=6.909178256988525,loss=6.923810005187988>
eval metrics=<mean_squared_error=27.047882080078125,loss=26.86684799194336>
train metrics=<mean_squared_error=6.8190460205078125,loss=6.79202938079834>
eval metrics=<mean_squared_error=26.209386825561523,loss=26.10053062438965>
train metrics=<mean_squared_error=6.7200140953063965,loss=6.737307071685791>
eval metrics=<mean_squared_error=26.682661056518555,loss=26.64984703063965>
也就是说,您的联合评估也在下降,只是比您的训练指标慢得多 - 有效地测量客户数据集的变化。您可以通过运行来验证这一点:
eval_metrics = evaluation(state.model, [datasets[0]])
print('eval metrics on 0th dataset={}'.format(eval_metrics))
eval_metrics = evaluation(state.model, [datasets[1]])
print('eval metrics on 1st dataset={}'.format(eval_metrics))
eval_metrics = evaluation(state.model, [datasets[2]])
print('eval metrics on 2nd dataset={}'.format(eval_metrics))
你会看到类似的结果
eval metrics on 0th dataset=<mean_squared_error=9.426984786987305,loss=9.431192398071289>
eval metrics on 1st dataset=<mean_squared_error=34.96992111206055,loss=34.96992492675781>
eval metrics on 2nd dataset=<mean_squared_error=72.94075775146484,loss=72.88787841796875>
因此您可以看到,您的平均模型在这三个数据集上的性能显着不同。
最后一点:您可能会注意到,您的最终结果evaluate
函数是not你的三次损失的平均值——这是因为evaluate
函数将是example- 加权,不client-加权——也就是说,拥有更多数据的客户在平均中获得更大的权重。
希望这可以帮助!