[django] 회귀분석 웹에 결과출력

GROOTY·2023년 5월 12일
0

❓문제) 원격 DB의 jikwon 테이블에서 근무년수에 대한 연봉을 이용하여 회귀분석 모델을 작성하시오.

장고로 작성한 웹에서 근무년수를 입력하면 예상 연봉이 나올 수 있도록 프로그래밍 하시오.
LinearRegression 사용. Ajax 처리!!!

먼저 요청명을 받는 urls.py 부터 확인

📌urls.py

from django.contrib import admin
from django.urls import path
from my_jikwon import views		# my_jikwon 어플리케이션 생성

urlpatterns = [
    path("admin/", admin.site.urls),
    
    # 요청 시 'show.html'로 render 역할
    path("", views.mainFunc),	
    
    # 요청 시 회귀분석 결과를 ajax 에게 전달역할
    path("predict", views.predictFunc),
]

📌show.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
function predFunc(){
	let sendData = {};
	let year = $("#year").val();
	sendData['year'] = year;
	// console.log(sendData);
	
	$(".predPay").empty();
	$(".r2s").empty();
	$(".listPay").empty();
	
	$.ajax({
		url:"predict",
		type:"POST",	// POST로 요청시 받는 함수 에 @csrf_exempt 적용해주어야한다.
		data:sendData,
		dataType:"json",
		success:function(data){
			// console.log(data)
			$(".predPay").append(`근무년수 <b>${year}년</b> 에 대한 예상 연봉은 <b>${data.new_pred}</b>`);
			
			$(".r2s").append(data.r2s);
			
			$(".listPay").append(data.pay_jik);
		}
	});
	 
}
</script>
</head>
<body>
<h2>근무년수에 따른 예상 연봉 알기</h2>
근무 년수 입력 : <input type="text" id="year" size="5" value="1">&nbsp;&nbsp;
<button onclick="predFunc()">연봉 확인</button>
<br><br>
<div class="predPay"></div>
설명력 : <span class="r2s"></span>
<br>
직업별 연봉 평균 <br>
<div class="listPay"></div>
</body>
</html>

📌views.py

from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
import json
from datetime import datetime
from django.http.response import HttpResponse, JsonResponse
import joblib
from my_jikwon.models import Jikwon

# Create your views here.
flag = False

def mainFunc(request):
    global flag
    
    # 이렇게 if 문을 걸어주면 처음 브라우저 서비스 시작하면서 모델을 한번만 만들고 계속 사용가능하다.
    if flag == False:
        makeModel()
        flag = True
        
    return render(request, 'show.html')

def makeModel():
    # jikwon 테이블에서 근무년수에 대한 연봉을 이용하여 회귀분석 모델을 작성
    datas = Jikwon.objects.values('jikwon_ibsail', 'jikwon_pay', 'jikwon_jik').all()
    jikdf = pd.DataFrame.from_records(datas)
    # print(jikdf.head(3), len(jikdf))
    
    # 근무년수 구하기
    for i in range(len(jikdf['jikwon_ibsail'])):
        # jikdf['jikwon_ibsail'][i] = int((datetime.now().date() - jikdf['jikwon_ibsail'][i]).days / 365)
        jikdf['jikwon_ibsail'][i] = int((datetime.now().date() - jikdf['jikwon_ibsail'][i]).days / 365)
    
    jikdf.columns = ['근무년수', '연봉', '직급']
    # print(jikdf.head(3))
    
    # train / test split (8:2)
    train_set, test_set = train_test_split(jikdf, test_size=0.2, random_state=12)
    print(train_set.shape, test_set.shape)
    # (24, 3) (6, 3)
    
    model_lm = LinearRegression().fit(X=train_set.iloc[:,[0]], y=train_set.iloc[:,[1]])
    
    # 성능 확인
    test_pred = model_lm.predict(test_set.iloc[:,[0]])
    print('연봉 예측값 :', test_pred[:5].flatten())
    print('연봉 실제값 :', test_set.iloc[:,[1]][:5].values.flatten())
    '''
    연봉 예측값 : [6827.05696203 4767.56329114 5282.43670886 3737.8164557  7341.93037975]
    연봉 실제값 : [7800 6600 5500 4000 8800]
    '''
    
    global r2s
    r2s = r2_score(test_set.iloc[:,[1]], test_pred)
    print('결정계수(설명력) :', r2s)
    #>> 결정계수(설명력) : 0.5523021663542762
    
    # 모델 저장(객체를 저장, 모델을 만들고 저장하는 과정 중요)
    joblib.dump(model_lm, 'django16linear/my_jikwon/static/jik_year.model')
    
    # 직급별 연봉 평균
    global pay_jik
    pay_jik = jikdf.groupby('직급').mean().round(1)
    print('pay_jik :', pay_jik)
    
@csrf_exempt    # csrf token 을 적용하지 않음
def predictFunc(request):
    year = request.POST.get('year')
    # print('year :', year)
    new_year = pd.DataFrame({'근무년수':[year]})
    
    # 모델을 읽어 해당 년도에 연봉을 예측하여 클라이언트에게 전송
    model = joblib.load('django16linear/my_jikwon/static/jik_year.model')
    
    new_pred = round(model.predict(new_year)[0][0], 2)
    print('new_pred : ', new_pred)
    
    context = {'new_pred':new_pred, 'r2s':r2s, 'pay_jik':pay_jik.to_html()}
    
    # return render(request, 'show.html', )
    # return HttpResponse(json.dumps(context), content_type='application/json')
    return JsonResponse(context)
profile
개발 시작

0개의 댓글