IAUAI/drop_prediction
0
1import gradio as gr2import pandas as pd3import pickle4import os5from docx import Document6from docx.shared import Inches7from docx.dml.color import ColorFormat8import sklearn9from lightgbm import LGBMClassifier10import numpy as np11import pandas as pd12from sklearn.linear_model import LogisticRegression13from sklearn.model_selection import train_test_split, GridSearchCV, StratifiedKFold14from imblearn.under_sampling import RandomUnderSampler15from sklearn.preprocessing import MinMaxScaler16from imblearn.over_sampling import SMOTE, BorderlineSMOTE 17from imblearn.pipeline import Pipeline as imbpipeline18from sklearn.pipeline import Pipeline19from sklearn.model_selection import cross_val_score, cross_val_predict20from sklearn.neighbors import KNeighborsClassifier21from sklearn import model_selection22from sklearn.neural_network import MLPClassifier23from sklearn.ensemble import RandomForestClassifier, BaggingClassifier, ExtraTreesClassifier,GradientBoostingClassifier, VotingClassifier24from sklearn.tree import DecisionTreeClassifier25from sklearn.linear_model import LogisticRegression26from sklearn.svm import SVC27from sklearn.metrics import confusion_matrix28from sklearn.feature_selection import SequentialFeatureSelector29from sklearn.model_selection import GridSearchCV, StratifiedKFold30import docx31from docx.enum.dml import MSO_THEME_COLOR_INDEX32 33def add_hyperlink(paragraph, text, url):34 # This gets access to the document.xml.rels file and gets a new relation id value35 part = paragraph.part36 r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True)37 38 # Create the w:hyperlink tag and add needed values39 hyperlink = docx.oxml.shared.OxmlElement('w:hyperlink')40 hyperlink.set(docx.oxml.shared.qn('r:id'), r_id, )41 42 # Create a w:r element and a new w:rPr element43 new_run = docx.oxml.shared.OxmlElement('w:r')44 rPr = docx.oxml.shared.OxmlElement('w:rPr')45 46 # Join all the xml elements together add add the required text to the w:r element47 new_run.append(rPr)48 new_run.text = text49 hyperlink.append(new_run)50 51 # Create a new Run object and add the hyperlink into it52 r = paragraph.add_run ()53 r._r.append (hyperlink)54 55 # A workaround for the lack of a hyperlink style (doesn't go purple after using the link)56 # Delete this if using a template that has the hyperlink style in it57 r.font.color.theme_color = MSO_THEME_COLOR_INDEX.HYPERLINK58 r.font.underline = True59 60 return hyperlink61 62def savedoc(document,name):63 def delete_paragraph(paragraph):64 p = paragraph._element65 p.getparent().remove(p)66 p._p = p._element = None67 for para in document.paragraphs:68 if para.text == '' and para.text != ' ':69 delete_paragraph(para)70 document.save(name)71 72from sklearn.metrics import accuracy_score, confusion_matrix, roc_auc_score, roc_curve, cohen_kappa_score, f1_score, recall_score, precision_score73def measures(predicted, y_test):74 accuracy = accuracy_score(y_test, predicted)75 precision = precision_score(y_test, predicted)76 recall = recall_score(y_test, predicted)77 f1 = f1_score(y_test, predicted)78 matrix = confusion_matrix(y_test, predicted)79 return accuracy80 81def greet(operation,filer):82 try:83 if filer == None:84 return None,"Invalid file submitted"85 import os86 coset = pd.read_csv(filer.name)87 coset = coset.dropna(how='any')88 document = Document('temp.docx')89 allowedcols = ['SID', 'TERM', 'CATALOG_NBR', 'INSTRUCTOR_ID', 'GRADE', 'CGPA', 'PROGRAM', 'PROGRAM.1']90 if operation == "retrain":91 allowedcols = allowedcols[1:]92 for col in coset.columns:93 if col not in allowedcols:94 return None,str(col)+" is undefined column name, allowed columns for training are "+str(allowedcols)95 wanted = coset#.drop(columns=['SUBJECT','SID','CRSE_ID','COURSE','ROLE','GPA','INPUT','STATUS','GRADUATION TERM','CLASS #','COLLEGE','COLLEGE.1'])96 def termize(x):97 if str(x)[-1] == "1":98 return 099 elif str(x)[-1] == "2":100 return 1101 else:102 return 2103 def shorten_major(x):104 if "Computer Science" in x:105 return "CS"106 elif "Computer Information" in x:107 return "CIS"108 elif "Artificial" in x:109 return "AI"110 elif "Cyber" in x:111 return "CYS"112 def binarize_grade(y):113 todrop = ['TR','DN','NP','IP']114 for element in todrop:115 if element in y:116 return -1117 if 'W' in y:118 return 1119 else:120 return 0121 122 wanted['PROGRAM.1'] = wanted['PROGRAM.1'].apply(shorten_major)123 wanted['GRADE'] = wanted['GRADE'].apply(binarize_grade)124 wanted['TERM'] = wanted['TERM'].apply(termize)125 deleteRow = wanted[wanted['GRADE'] == -1].index126 wanted.drop(deleteRow, inplace=True)127 majors = []128 catalog = []129 acad_prog = []130 instructor = []131 def numberize(y):132 if y not in majors:133 majors.append(y)134 return majors.index(y)135 else:136 return majors.index(y)137 138 def catalogize(z):139 if z not in catalog:140 catalog.append(z)141 return catalog.index(z)142 else:143 return catalog.index(z)144 145 def acadize(w):146 if w not in acad_prog:147 acad_prog.append(w)148 return acad_prog.index(w)149 else:150 return acad_prog.index(w)151 def instructerize(w):152 if w not in instructor:153 instructor.append(w)154 return instructor.index(w)155 else:156 return instructor.index(w)157 158 def removestring(w):159 if any(c.isalpha() for c in w):160 return w[:-1]161 else:162 return w163 164 wanted['PROGRAM.1'] = wanted['PROGRAM.1'].apply(numberize)165 wanted['CATALOG_NBR'] = wanted['CATALOG_NBR'].apply(catalogize)166 wanted['PROGRAM'] = wanted['PROGRAM'].apply(acadize)167 wanted['INSTRUCTOR_ID'] = wanted['INSTRUCTOR_ID'].apply(instructerize)168 document.add_paragraph(' ')169 document.add_heading('Retraining report', 0)170 document.add_paragraph('This report consists of the models retraining information on the new dataset with ('+str(len(coset))+') records')171 records = []172 173 X = wanted.drop(columns=['GRADE'])174 y = wanted['GRADE']175 smote = BorderlineSMOTE(random_state = 11)176 X_smote, y_smote = smote.fit_resample(X, y)177 kf = StratifiedKFold(n_splits=10)178 models1 = [KNeighborsClassifier(leaf_size=10,metric='manhattan'),179 RandomForestClassifier(max_depth=100),180 LGBMClassifier(n_estimators=200, num_leaves=60),181 VotingClassifier(estimators=[('knn',182 KNeighborsClassifier(leaf_size=10,183 metric='manhattan')),184 ('rf', RandomForestClassifier(max_depth=100)),('gm',LGBMClassifier(n_estimators=200, num_leaves=60))])]185 metrics = dict()186 for model in models1:187 model.fit(X_smote,y_smote)188 preds = cross_val_predict(model, X_smote.values,y_smote.values, cv=kf, n_jobs=-1,);189 metrics[model] = measures(preds,y_smote.values)190 records.append(((str(type(model).__name__),str(metrics[model]))))191 document.add_paragraph(' ')192 records = tuple(records)193 194 table = document.add_table(rows=1, cols=2)195 hdr_cells = table.rows[0].cells196 hdr_cells[0].text = 'Name'197 hdr_cells[1].text = 'Accuracy'198 for ind,qty in records:199 paragraph = document.add_paragraph()200 row_cells = table.add_row().cells201 row_cells[0].text = str(ind)202 row_cells[1].text = str(qty)203 table.style = 'TableGrid'204 205 dir_name = str(os.getcwd())206 test = os.listdir(dir_name)207 number = 0208 for item in test:209 if item.endswith(".sav") and int(item.split("=")[0]) >= number:210 number = int(item.split("=")[0])211 #os.remove(os.path.join(dir_name, item))212 acc = metrics[max(metrics, key=metrics.get)]213 model = max(metrics, key=metrics.get)214 number = number + 1215 filename = str(number)+"="+type(model).__name__+'='+str(acc)+'.sav'216 217 datavalues = {"majors":str(majors),218 'acad_prog':str(acad_prog),219 'catalog':str(catalog),220 'instructor':str(instructor)221 }222 223 dfv = pd.DataFrame(datavalues,index=[0])224 dfv.to_csv(str(number)+"="+"values.csv")225 226 document.add_paragraph(" ")227 document.add_paragraph(type(model).__name__+' has been chosen as the prediction model for achieving an accuracy of '+str(acc)+'%')228 pickle.dump(model, open(filename, 'wb'))229 document.add_paragraph(" ")230 p = document.add_paragraph('For more like this contact us at ')231 add_hyperlink(p, 'contact@mustafasa.com', "contact@mustafasa.com")232 savedoc(document,'retraining_report.docx')233 #document.save('retraining_report.docx')234 return 'retraining_report.docx',str(type(model).__name__+' has been chosen as the prediction model for achieving an accuracy of '+str(round(acc*100,2))+'%')235 allowedcols.remove('GRADE')236 for col in coset.columns:237 if col not in allowedcols:238 return None,str(col)+" is undefined column name, allowed columns for prediction are "+str(allowedcols)239 majors = []240 catalog = []241 acad_prog = []242 instructor = []243 dir_name = str(os.getcwd())244 test = os.listdir(dir_name)245 modelname = ""246 maxnum = 0247 for item in test:248 if item.endswith(".sav") and int(item.split("=")[0]) > maxnum:249 maxnum = int(item.split("=")[0])250 modelname = item251 if maxnum == 0:252 return None,"No model found, please use retrain operation to build one"253 dfv = pd.read_csv(str(maxnum)+"=values.csv")254 255 cols = [majors,acad_prog,catalog,instructor]256 indexc = 0257 258 for column in dfv.columns:259 if "[" in str(dfv[column][0]):260 l = dfv[column][0].replace("'",'')261 cols[indexc][:] = str(l).strip('][').split(', ')262 263 for i,e in enumerate(cols[indexc]):264 cols[indexc][i] = e.replace(' ','')265 print(cols[indexc])266 indexc = indexc + 1267 #modelname = "VotingClassifier=0.95756598831352.sav"268 loaded_model = pickle.load(open(modelname, 'rb'))269 droppers = 0270 total = 0271 document.add_paragraph(' ')272 document.add_heading('Subjects drop prediction report', 0)273 document.add_paragraph('This report consists of students who might potentially drop courses they currently are studying based on the supplied information')274 275 records = []276 for row in coset.iterrows():277 row = list(row)[1]278 semester = 1279 row['CATALOG_NBR'] = str(row['CATALOG_NBR']).replace(' ', '')280 row['TERM'] = str(row['TERM'])281 if row['TERM'][-1] == 2:282 semester = 2283 elif row['TERM'][-1] == 5:284 semester = 3285 c_id = catalog.index(str(row['CATALOG_NBR']))286 in_id = instructor.index(str(row['INSTRUCTOR_ID']))287 p_id = acad_prog.index(row['PROGRAM'])288 major = 0289 x = row['PROGRAM.1']290 if "Computer Science" in x:291 major = 0292 elif "Computer Information" in x:293 major = 1294 elif "Artificial" in x:295 major = 3296 elif "Cyber" in x:297 major = 2298 gpa = row['CGPA']299 prediction = loaded_model.predict([[semester,c_id,in_id,gpa,p_id,major]])[0]300 total = total + 1301 records.append((str(total),str(row['SID']),str(row['TERM']),str(row['CATALOG_NBR']),str(row['INSTRUCTOR_ID']),str(row['CGPA']),str(row['PROGRAM']),str(row['PROGRAM.1']),str(prediction)))302 if prediction == 1:303 droppers = droppers + 1304 document.add_paragraph(' ')305 records = tuple(records)306 307 table = document.add_table(rows=1, cols=9)308 hdr_cells = table.rows[0].cells309 hdr_cells[0].text = 'Index'310 hdr_cells[1].text = 'Student ID'311 hdr_cells[2].text = 'Term'312 hdr_cells[3].text = 'Catalog ID'313 hdr_cells[4].text = 'Instructor ID'314 hdr_cells[5].text = 'Cummulative GPA'315 hdr_cells[6].text = 'Academic Program'316 hdr_cells[7].text = 'Major'317 hdr_cells[8].text = 'Possible Drop Prediction'318 for ind,qty, id1, desc, inst, cgpa,aprog,maj,pred in records:319 paragraph = document.add_paragraph()320 row_cells = table.add_row().cells321 row_cells[0].text = ind322 row_cells[1].text = str(qty)323 row_cells[2].text = id1324 row_cells[3].text = desc325 row_cells[4].text = inst326 row_cells[5].text = cgpa327 row_cells[6].text = aprog328 row_cells[7].text = maj329 if pred == "1":330 pred = "Yes"331 else:332 pred = "No"333 row_cells[8].text = pred334 335 table.style = 'TableGrid'336 #document.add_page_break()337 document.add_paragraph(" ")338 modelname = modelname.split("=")339 lastpara = 'Out of '+str(total)+' records, it is predicted that '+str(droppers)+' courses might be withdrawn from (Prediction model name:'+modelname[1]+'/Accuracy: '+str(float(modelname[2][0:6])*100)+'%)'340 document.add_paragraph(lastpara)341 savedoc(document,'drop_prediction_report.docx')342 #document.save('drop_prediction_report.docx')343 return 'drop_prediction_report.docx', lastpara+" (Model no."+modelname[0]+")"344 except Exception as e:345 return None,str(e)346 347iface = gr.Interface(fn=greet, inputs=[gr.Radio(["predict",'retrain'],value="predict"),"file"], outputs=[gr.File(label='Report generated'),gr.Text(label='Log')],debug=True)348iface.launch()