Heroku 内存配额在使用 SKLearn 的 Django 项目中大大超过



我已经在 Heroku 上部署了一个 Django 应用程序,目标是允许受信任的、已知的内部用户上传 CSV 文件,点击"运行",在幕后,Django 应用程序:

  1. 加载保存的 SKlearn 管道.pkl模型(假设大小为 120 MB)
  2. 使用熊猫读取用户的 CSV 数据
  3. 使用 CSV 数据作为输入调用模型上的predict
  4. 使用 Django 存储将文件输出到 S3

这适用于小型 CSV 文件,但如果用户上传大型 CSV 文件,则会导致Memory quota vastly exceeded...较大的CSV文件会增加内存消耗是有道理的。

我不知道该在哪里调整。我想知道是否有人在部署 sklearn 模型时遇到过类似的情况以及他们如何"解决"它?

我的想法是:

  1. 识别内存泄漏?甚至不知道从哪里开始。DjangoDEBUG设置为False.
  2. 更改我的芹菜任务以块的形式处理输入的文件?
  3. 使用
  4. joblib 以某种方式制作一个较小的 SKLearn 管道文件(我已经使用 压缩=1)?
  5. 增加希罗库测功机
  6. ? 工人?

我的 django models.py 看起来像这样:

from django.db import models
from django.urls import reverse

class MLModel(models.Model):
name = models.CharField(max_length=80)
file = models.FileField(upload_to="models/")
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name

class Upload(models.Model):
name = models.CharField(max_length=100)
mlmodel = models.ForeignKey(MLModel, on_delete=models.CASCADE)
file = models.FileField(upload_to='data/')
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('edit', kwargs={'pk': self.pk})

我的芹菜任务如下所示:

@shared_task
def piparoo(id):
instance = Upload.objects.get(id=id)
model = joblib.load(instance.mlmodel.file.storage.open(instance.mlmodel.file.name))
data = pd.read_csv(instance.file)
data['Predicted'] = model.predict(data)
buffer = StringIO()
data.to_csv(buffer, index=False)
content = buffer.getvalue().encode('utf-8')
default_storage.save('output/results_{}.csv'.format(id), ContentFile(content))

Heroku 日志:

2018-04-12T06:12:53.592922+00:00 app[worker.1]: [2018-04-12 06:12:53,592: INFO/MainProcess] Received task: predictions.tasks.piparoo[f1ca09e1-6bba-4115-8989-04bb32d4f08e]
2018-04-12T06:12:53.737378+00:00 heroku[router]: at=info method=GET path="/predict/" host=tdmpredict.herokuapp.com request_id=ffad9785-5cb6-4e3c-a87c-94cbca47d109 fwd="24.16.35.31" dyno=web.1 connect=0
ms service=33ms status=200 bytes=6347 protocol=https
2018-04-12T06:13:08.054486+00:00 heroku[worker.1]: Error R14 (Memory quota exceeded)
2018-04-12T06:13:08.054399+00:00 heroku[worker.1]: Process running mem=572M(111.9%)
2018-04-12T06:13:28.026973+00:00 heroku[worker.1]: Error R15 (Memory quota vastly exceeded)
2018-04-12T06:13:28.026765+00:00 heroku[worker.1]: Process running mem=1075M(210.1%)
2018-04-12T06:13:28.026973+00:00 heroku[worker.1]: Stopping process with SIGKILL
2018-04-12T06:13:28.187650+00:00 heroku[worker.1]: Process exited with status 137
2018-04-12T06:13:28.306221+00:00 heroku[worker.1]: State changed from up to crashed

解决了我的问题的解决方案(以常识性的方式)。

不要一次将用户的 CSV 文件读入内存,而是使用 Pandaschunksize参数分块处理它,然后在最后将数据帧列表连接成一个。我还删除了模型 (120 MB),以尝试释放该内存以供将来处理。

我的芹菜任务现在看起来像这样:

@shared_task
def piparoo(id):
instance = Upload.objects.get(id=id)
model = joblib.load(instance.mlmodel.file.storage.open(instance.mlmodel.file.name))
final = []
for chunk in pd.read_csv(instance.file, chunksize=5000):
chunk['Predicted'] = model.predict(chunk)
final.append(chunk)
del model
final = pd.concat(final)
buffer = StringIO()
final.to_csv(buffer, index=False)
content = buffer.getvalue().encode('utf-8')
default_storage.save('output/results_{}.csv'.format(id), ContentFile(content))

相关内容

  • 没有找到相关文章

最新更新