From 065bf310d03813377eefb191962e1ef12c876608 Mon Sep 17 00:00:00 2001 From: Ryan Christopher Bahillo Date: Sun, 4 Sep 2022 20:34:14 +0800 Subject: [PATCH] =?UTF-8?q?fix=20admin=20and=20app=20(=20=CE=B2=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- website/base/__pycache__/admin.cpython-38.pyc | Bin 319 -> 620 bytes .../base/__pycache__/models.cpython-38.pyc | Bin 996 -> 1300 bytes website/base/__pycache__/views.cpython-38.pyc | Bin 4905 -> 5420 bytes website/base/admin.py | 10 +++- website/base/models.py | 13 ++++- website/base/views.py | 45 ++++++++++++------ 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/website/base/__pycache__/admin.cpython-38.pyc b/website/base/__pycache__/admin.cpython-38.pyc index 2ef8be76cc6df576633f4a05378af9703a92011e..1b467f42c450ed4f2889c7969bf1c675759339f4 100644 GIT binary patch literal 620 zcmYjO!EV$r5VhlMHchkJ9x8$OgFQ4KfDl5o;)3X<>?Mj+c{4-STgQoPmkNm+oGS4T z?XkZUj-2`noEWD;+L31b#_xGNW3LyBjFG*#JE?zj#{Pt4-(pJMkvpIO47g@3FF9ur zfzVMaO3}t;OgV#C&)TF+Mm*E=HZ4=mknaxeGZYVWX2S7^Q%q1m@+*Qlq(9jYULL~1 zC0k`rbQ4?gVJ4wf=83vut7ynSTd54frw&jL%P~`?x%ATCI8tZ5#VexFBW0<@8r4^{ zgcFAb(AH6?JDH$0_(yVgOyN7b=}5t-I!fYHhso8sXG$(J6P@+iq9g;>IbD)kZq3 z#$k*8+i=pE{ZY@ykq$$j;{d`Q5x!XE-%nKPA8K7(y z5Icn>m_d_u;uK?MKTY<@yBXCbZ?P0-mZaX|C`wJwEG|hcTFFqv2{fjNbFvqsrv!&h XZhlH>PO2Rv$Y?eo!NVxP%)P4i>l9_5W+2EUmf(TxE z@n%?WwwK=g2!540m)<=UdMJHwR1l;y%%3;&=Dm6EH$N+v)o>>Wst%2{^QimLorDE^ zn*8_>sVQ0e2C^=LuikD$!j=<VLCE6lTjGS$IQs(#8gz2Irp|9tJ>G$s1ePTuY9 z&^^7ko*fj4SY0xeG}R+a(~w^iBo3TJ+nDuoB{w#Zl?zV#NV=K{oP4(7Ty*&Vlh%x=@Gh; zEEBq#tWe8-@k`8~VL%i?<3c<6n`_TJ0) zw?^4$tRK4X#C3ehkw>$vuUMECzGmU?!Z$2T2j@t3!-3K|+gF5_6X862{!3?pybMN{ mNqlHPUEo47blWTJc~rD5p9?nr8h!M*uikU-Hjaq8t>7Oz<%5U- delta 336 zcmbQj^@N=-l$V!_0SNN1{z*E(*lUW&4MdgcAOG+~H(u?(c zU0pmKg2;r7Mv>?iX?!R6iH0}#^|Y1!~$fq0&%ebkli4Y74DuHjmM)O%a&~Y*p_AaCzcZ{StoHe8?%s&y=-7(d-GGUT6R^6di*ny zC8wvoA*KiIq7)}wWNV7cZUy86hfv(O05_nD0~g>roH*` z)(~j+25wg!>vVnVV{5J66s1kET@OYVL%bK-c@|+9A%%d3_y|Jo2*yD2)#}a;c5^fU z0*vwklr@UA!yn2je1Cw?Ns<;Jf^?`P2lOhC{tiLvZ;;1yr3ju>o%@a2R?`nTb<5g$ zOnoYjn+%DqZ7VS2C}@K68NioJVq0Kx00coKY(ijf^Uxrl0DZALm`{WJlAWFEu47F> z%Tqf=kYBKK5)??y73{PK6i8wdM(-#OHGacCm)dn1lKO_?_K1k=f!Pfa?Zl*U zKwEAv3%lk9al`OMM4uhE6?wc~)8I=j-Kt@37M+x+$yZ>OLFEAGE#xeiqz3 zB@65%JGHO06^Nf^ZyCIW6-rbOKgCXP>cO+n{oyGA}1OXTh&Y zan3&9Sr8ZO*D+k}i|llY94PLTctcLHGi~L^Nq1UKcP@!VIoS@v^;_gTd5>Ht-zGty z*PzdmdqR8#$4f=LDNl&6wxrUgov*QZcJ@GF=ekpWK^`d(F6ZG}*jLzvebt?jGu<=s z+@zPm@aya%9M>Xy$}?xhbO(9QR*Fp8z#7= zyl)!gr5Mz{#2fcZyx(~rLL8wVVCyeE03A?ry!v>;``q}{%lF=&4_9t3Ut4?o>buLO zO`qQL6@L2(&HJ>nr_9amDWy%YtKpi8DnE-uPkDdtT}~|f`nDxDn~cw*60du2!Mvph zIU?o#$jtQdNl^MK-)(TbB)y-TH5&DL!}GDh<(+12bB%8`FnM`zh3{QanvSpSRK=#R z+0Cs6$E@s|*Or&AUankUUA^fWaPRVf8?CuxHT=*$z9lRkf_@x)BRuT=HJr-o+}dt_ zY;hG;c-D1 zN2;7f013&vLL}so3KdERk{hE;>E;Zk!kMCw1GGmdkxB@$qho%-G+zv@@S|AX%iTnR zAujUwo4Y)ZM0*e8X6wx9Ct9&oDiwSDc&%Em->%l~R5q&(R<}5>!xDmcF)8y;*<~<%on;&3jeFrwV>hP;r2{m@Nckc5Q zY{mP9zm3qUB7Otm7D67OfPl}yZaCnvf_MhF2v9bj5)ruZDvy0*5rS{GZoP@GRR@n? j92mt{b8y-N1R~&{4GLv|YKqZgP*XQlLo-?=ZuI^iF$c>( delta 2659 zcmbtW&5s*N6|bsp+iko3F}BAaV|(n(SK^thv&m*A*-h9e8&Kdtv=HsWT13Y2>+!hb zk4bgSh8fnvyGfz z=NoyyE;I@dfhd>|gE%B0*$Fk4V4+cj6r`V$M#<741B(+1S;##lW7;S~9ty}=h9xLs zUAar31m&j$%2vv*+ULevV+F$ZNp1N#@!q0Oy+706(5&|ZR?A0G!;jfK#I45%mLqsh z^$9O~e`5F2DeO1~0-**?;?FDImiFFg5h;hMhb_mt)a$-)z1u- zb?+Z~Wpo`Wnyo`1M_eWXA~+36IyE3Tqcb|Dt|r2EL~0@mp$T(!zo$zbi~{b(BUT`` zIgQQ8F+cDUKk`5PpbW@hhq)mUmm!?p7>UF*DUBI*!w_{N9pXl@m}0?B*-WVh=7hR2 zh{;$pEo0Nnj8GyLr7@;oB+uxBpo$)6EO zex!}5KR&6(Klr0NO5t*8u_*FB;pc8frbIqNWCs1QDAQs|CSajJUPC3H(Z@S7IxWid3~i7mwiZ+i=^Ky# z4#k%|l$e%e6ulZn|CXeQEfZZHMXzL$QkGeyOmZudj8On{aP?Fh~&a%3REY| zSNt^n+-LL=T6Bsb4On?Gz}|pWScCNrg^h`(B<=HZNtR^<&dZXl>@smd#>N!+7bZdX z9L`jeMYM1QcfN*JZpszdgsll1Gu-_GT$IbI1+Sd=Y^1`fYH!&Wr?1E=4pq8u*>(F; zhsxFFt8#UE8Le6qSD+4;#_Y!#cU`VeUlUj5+89p?CEp<1<)KBR9k~$;Nbg9WKL_8H3j_60S}dY)>@z{M+*UQEZ=@=5<_Z2d?3|izXr21roIaT|{_s;;ozvzatMB2ux>BU3@hvsUnrB46wDRUW*tf*q z5crBBo+Q1wao|{7$$Q_9zC#P%@1q6pZ_ze2y}Ra>Q2fq;BZhtN`{t9pKHRqk^S~3{ z6&4SuSx{TTBi`*;ZkY|8d5~NE;rkZX6qzB^HhD?4S3MrvrHx+l=MSAH4@>pS9X-i-?0>JE-9RTmJOXE1gqhYgH}ajQay|dDf^~$N!EdUzzn^Dr6kq6tJG3Krw3K*X!I^s|(y>HS?eT&0D`Y$V z<&1_Uu^5yOiT6qJ_UK(?wUv86`&3&M|L##^B$cE|fM9gedl(PNcB|KW*lIs&?zINc zvv`fob;s)M@_m#(tA){Qb_ZS2Z2k_Jj=vB+%pC>7omS6VOI1BH8NPAFUkPZI0DHuE z9W+TX^XngJ>gsEv4mO!G{}$08pl$1oI^Dq^aKQ0f!t{N9SU$1ZcVGQw zdGBg^bBC)H9R)8o({HJl16O5!S#N^4;F>30KbxeqT|8`?!rQhrgvdfx$t4{{wzkac?Pjpg_d} z|EhwD0(E-$K*3PKWrT)-o9Ub7>vUHA+y2YPxQXfPpl7|Q-a3v7{3ISG_0BpvgeJ!2 T@y}9t0F4kH#E>x}2_yVpgs)0W diff --git a/website/base/admin.py b/website/base/admin.py index dd9bfac6..f503ea54 100644 --- a/website/base/admin.py +++ b/website/base/admin.py @@ -1,6 +1,14 @@ from django.contrib import admin from .models import TrainedModel, TrainingStatus +from django.db.models.signals import pre_delete +from django.dispatch.dispatcher import receiver # Register your models here. admin.site.register(TrainedModel) -admin.site.register(TrainingStatus) \ No newline at end of file +admin.site.register(TrainingStatus) + + +@receiver(pre_delete, sender=TrainedModel) +def onTrainedModelDelete(sender, instance, **kwargs): + # Pass false so FileField doesn't save the model. + instance.file.delete(False) \ No newline at end of file diff --git a/website/base/models.py b/website/base/models.py index 59a49f72..5007ebc2 100644 --- a/website/base/models.py +++ b/website/base/models.py @@ -2,7 +2,7 @@ from django.contrib.auth.models import User -class TrainedModel(models.Model): +class TrainedModel(models.Model): owner = models.ForeignKey(User, default=None, on_delete=models.CASCADE) model_name = models.CharField(max_length=150) created_at = models.DateTimeField(auto_now_add=True) @@ -11,8 +11,17 @@ class TrainedModel(models.Model): upload_to='TrainedModels', default='settings.MEDIA_ROOT/default.jpg' ) + def __str__(self) -> str: + return f'{self.owner.username}__{self.model_name}' + class TrainingStatus(models.Model): owner = models.ForeignKey(User, on_delete=models.CASCADE) message_status = models.CharField(max_length=150) - + + def __str__(self) -> str: + return self.owner.username + + + + diff --git a/website/base/views.py b/website/base/views.py index dc8ecd7d..cb1c63c0 100644 --- a/website/base/views.py +++ b/website/base/views.py @@ -3,12 +3,14 @@ from base.utils import hex_to_c_array, rmv_file_spaces from base.models import TrainedModel, TrainingStatus from accounts.models import Profile +from django.conf import settings from django.core.files.base import File from django.shortcuts import render from tensorflow import keras import tensorflow as tf import pandas as pd import numpy as np +import asyncio import csv import os @@ -29,13 +31,20 @@ def app(request): +async def timer(t): + await asyncio.sleep(t) + +async def pause(t): + await timer(t) + def train_model(request): if request.method == 'POST': data = request.POST.get('data') named_model = request.POST.get('model_name') + if named_model == '': - named_model = request.user.username + '_no_name_model' + named_model = 'NO_NAME_MODEL' parsed_csv = list(csv.reader(data.split(';'))) @@ -56,7 +65,7 @@ def train_model(request): msg.message_status = 'Normalizing data ...' msg.save() # ----------------------------------------------------- - + asyncio.run(pause(t=1)) for hotspot_index in range(NUM_HOTSPOT): target = HOTSPOT[hotspot_index] @@ -109,7 +118,7 @@ def train_model(request): inputs_train, inputs_test, inputs_validate = np.split(inputs, [TRAIN_SPLIT, TEST_SPLIT]) outputs_train, outputs_test, outputs_validate = np.split(outputs, [TRAIN_SPLIT, TEST_SPLIT]) - + # build the model and train it model = tf.keras.Sequential() model.add(tf.keras.layers.Dense(50, activation='relu')) # relu is used for performance @@ -118,7 +127,7 @@ def train_model(request): model.compile(optimizer='rmsprop', loss='mse', metrics=['mae']) history = model.fit(inputs_train, outputs_train, epochs=N_EPOCH, batch_size=1, validation_data=(inputs_validate, outputs_validate), - callbacks=[CustomCallback(msg)]) + callbacks=[EpochPrintingCallback(msg, N_EPOCH)]) # print("Evaluate on test data") @@ -137,7 +146,6 @@ def train_model(request): # # print the predictions and the expected ouputs # print("predictions =\n", np.round(predictions, decimals=3)) - msg.message_status = 'Converting to tflite ...' msg.save() @@ -147,24 +155,25 @@ def train_model(request): tflite_model = converter.convert() # Save as temporary - with open('static/temp_model.h', 'w') as temp: + USER_TEMP_FILE = os.path.join(settings.MEDIA_ROOT, request.user.username + '_TEMPFILE.h') + with open(USER_TEMP_FILE, 'w') as temp: temp.write(hex_to_c_array(tflite_model)) # Then save to database - with open('static/temp_model.h', 'rb') as f: + with open(USER_TEMP_FILE, 'rb') as f: fs = TrainedModel( owner=request.user, model_name=named_model, - file=File(f, name=str(named_model).replace(" ", "_") + '.h') + file=File(f, name=str(named_model).replace(" ", "_") + f'--{request.user.username}' + '.h') ) fs.save() - model_string = rmv_file_spaces('static/temp_model.h', exclude='unsigned char model[] = {') + model_string = rmv_file_spaces(USER_TEMP_FILE, exclude='unsigned char model[] = {') msg.message_status = 'Done!' msg.save() - os.remove('static/temp_model.h') # end of using temp model + os.remove(USER_TEMP_FILE) # end of using temp model context = {'model_string': model_string} return JsonResponse(context) @@ -181,15 +190,21 @@ def get_status(request): -class CustomCallback(keras.callbacks.Callback): - def __init__(self, callback_handler): +class EpochPrintingCallback(keras.callbacks.Callback): + def __init__(self, callback_handler, N_EPOCH): self.callback_handler = callback_handler + self.N_EPOCH = N_EPOCH + + asyncio.run(pause(t=1)) + self.callback_handler.message_status = f'Training your model (Epoch: 0/{self.N_EPOCH})...' + self.callback_handler.save() - def on_epoch_begin(self, epoch, logs=None): + def on_epoch_end(self, epoch, logs=None): if epoch % 50 == 0: - self.callback_handler.message_status = f'Training your model (Epoch: {epoch})...' + self.callback_handler.message_status = f'Training your model (Epoch: {epoch+50}/{self.N_EPOCH})...' self.callback_handler.save() - print('###############################################################') + +