728x90
반응형

안녕하세요? 다덜 오랜만입니다.
너무나 할게 없어서 후기 좀 끄적이려 들어왔습니다.
(이제 무도짤을 곁들인...)




! 우선 !



저는 2023 3회차 필기 합격 후
2024 1회차 실기 합격으로
정보처리기사 취득에 성공을 했답니다!


일단 저는...
비전공자이며
6개월 간 IT 관련 수업을 받았고
정처기 이전에 adsp, sqld 를 취득한 경험이 있습니다.

지금 정처기 합격자 발표되고 한달 정도 지났는데
기순교절시논우
데스제외공내
아직도 기억나요
(사실 이거빼고 나머지는 기억 안나요)

그럼 그닥 도움되지 않을 것 같지만
일단 한번 끄적여보겠습니다.


1. 공부기간

필기 > 2주
필기 때는 프로젝트 기간이랑 겹쳐서 공부는 많이 못했던 것 같아요.
근데 지금 생각해보면 이론 후루룩 빠르게 보고 기출만 계속 돌린다면  2주면 충분했던 것 같습니다.
마지막엔 문제만 계속 푸는게 오히려 힘들었어요.

실기 > 1달
실기 같은 경우에는 그 당시 백수였던 상태라 진짜 이때 아니면 평생 못딴다라는 마인드로 정처기 공부하면서 한달을 다 보낸 것 같아요.
하루 계획표가
기상 >  밥 먹기 > 카페가서 공부하기 > 집와서 밥먹기 > 공부하기 > 잠자기 였답니다.

2. 교재

필기 > 이기적 정보처리기사 필기 절대족보
필기는 당시 시간도 없고 그래서 이론 많은 문제집 사면 다 보지도 못할게 뻔했기 때문에 이론은 간단하게 문제는 많이 나온 책으로 골랐어요.
사실 그냥 두꺼운 책 사기 싫어서 조감자씨의 교재를 따라샀답니다.
문제집이 얇아도 기출문제는 충분히 들어있어서 좋았던 것 같아요!
어차피 부족한 기출문제는 다 인터넷에 나와있어서 필기는 교재가 크게 중요하지 않다고 봅니다.


실기 > 수제비 2024 정보처리기사 실기
실기 책은 구매할 당시 엄청 고민했던 것 같아요.
분명 이것저것 엄청 따졌던 것 같은데...
지금 와보니 왜 수제비를 샀는지... 기억이 안나네요..?
근데 뭐 교재 자체는 괜찮은 것 같습니다.
두음법칙은 처음에 뭐 이런 억지가;; 하다가도 그 방법으로 외우고 있더라구요?
비전공자 기준 이론도 적당히 잘 설명되어있는 것 같았고, 문제도 충분히 수록되어 있었습니다.
이론이 너무 많아서 읽어도 읽어도 끝나지 않았던 것 같긴 한데, 저에게 합격을 가져다주었으니 추천합니다 ^ㅁ^/

3. 공부 방법 및 시험 후기

필기 > 기출이 답!
필기는 일단 이론은 한 2번 정도 읽어봤습니다. 근데 대충을 곁들인...
시간이 많이 없어서 빠르게 읽고 남은 기간엔 계속 문제만 풀었습니다.
그리고 시험을 봐본 결과 정말 외울정도로 계속 풀어보는게 답인 것 같아요.
자세히 기억은 안나는데 2020년도 기출부터 2023년도 기출까지 온라인 상에 나와있는 기출문제는 거의 다 모아서 풀었어요!
물론 책에 있는 예상문제? 같은 문제들도 전부 다 풀었습니다.
거의 일주일 정도는 문제풀기만 반복했고
그 결과...

나름 높은 점수로 합격했습니다.
4과목에서 기출문제가 많이 나와서 가장 높은 점수를 받았고 나머지 과목도 풀어봤던 문제들이 많이 나왔던 것 같아요!
결론! 기출을 풉시다.

실기 > 팁은 없지만 할 말은 많아요.
사실 실기 공부는 저에겐 팁이랄게 딱히...
이론 읽어 보고 문제 풀어보면?

이론적인 건 정말 1도 모르겠더라구요?
오히려 프로그래밍 언어 문제 푸는게 나을 정도로 이론은 암기 아니면 답이 없다고  생각하고 개념은 한 5번 정도 읽은 것 같고 문제는 거의 다 외울 정도로? 공부했습니다.

음, 그리고 수제비 카페도 정말 자주 이용했습니다!
수제비에 올려진 기출문제도 풀고 그 날마다? 1문제씩 올려주는 게시판이 있는데, 거기에 올려진 문제들 다 모아서 풀었어요.
그래서 교재에 있는 문제, 기출문제, 예상문제 등 답을 거의 다 외웠답니다.

그래서 나름 열심히 하고 이정도면 되겟지 하는 마음으로 시험장으로 갔는데...
롸? 너무 어렵더라구요?
그래도 1회차는 쉽다길래 기대했는데...


특히 프로그래밍 언어 문제가 생각보다 많이 나와서 당황했습니다.
정말 이론 문제 다 맞는거 아닌 이상 합격 못할 것 같아서 일단
이론 문제 먼저 집중해서 풀고 언어 문제 풀었던 것 같아요.

이론 문제 확실한 건 다 풀어주고 헷갈리는 문제들 다시 보는데
우선, IP 주소 문제는 일단 거르고...
JOIN 종류 문제? 나름 SQL했다고 JOIN 아는데! 자연조인, 동등조인 이런건 모른단 말이에요.( 진짜 수제비 책에도 안나옴;; )
프로그래밍 언어 문제들은 사실 지금 생각하면 어떻게 푼지 기억도 안나긴해요.
침착하고 내가 컴퓨터가 되었다고 생각하며 내 안에서 코드를 돌린다는 마음으로 차근차근 풀었던 것 같은데 그냥 제 체감상 기출문제, 예상문제로 풀었던 언어 문제들 보단 어려웠다?

그래도 일단 정확히 하는 문제들은 다 풀어놓고
프로그래밍 언어 문제는 코드 흐름 생각하면서 천천히 풀면
아예 안풀릴 정도는 아니니 공부할 때 문제들 많이 풀어보면서 감 잡는게 중요할 것 같아요.

쨌든 어찌저찌 다 풀고 답 적은거 기억해서 카페에서 답 맞춰보니
예상 점수는 70점이 나왔습니다.
그래도 혹시나 하는 불안한 마음이 있었지만...


다행히 74점으로 합격했습니다!

솔직히 70점보다 높을거란 기대는 안했는데, 저 4점은 어디서 나온건지 모르겟어요;;
뭐 일단 합격했으니까!

^ㅁ^

제 체감상 adsp, sqld보다는
확실히 난이도 있는 시험인 것 같습니다.
나름 열심히 했다고 생각했는데도 시험장에서 문제를 보니 막막하더라구요.
그래도 이론적인 건 자주 기출되던 문제에서 나오는 것도 꽤 있었고
예를들어 응집도/결합도 , 정규화, 디자인패턴, 보안관련 용어 등
이런 개념은 확실히 전부 외우고 가는게 좋을 것 같아요!
언어는 문제는 많이 풀어보기? 코드 한줄 한줄 어떻게 어떤 순서로 진행되는지 공부하면 도움이 많이 될 것 같습니다.
그럼 당신의 점수는?



퇴근이다.
집에 가야해요.

우연히 제 글을 읽게 된 정처기 공부하시는 여러분들
항상 화이팅 하시고
제 주저리 주저리 글 읽어주셔서 감사합니다.

그럼...

728x90
반응형
728x90
반응형

PyMySQL 설치

conda install -c conda-forge PyMySQL

mysqlapp 생성

python manage.py startapp mysqlapp

mysqlapp web 구현

mysqlapp
- 함수명 index 생성
- HttpResponse("index 페이지 입니다." ) 출력
- mysqlapp에 urls.py 생성
- url 패턴 : http ://127.0.0.1:8000/mysql/
  • mysqlapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/mysql/
    path('', views.indexHtml ),
]
  • config > urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    ### mysqlapp의 urls.py 사용하기
    # http://127.0.0.1:8000/mysql/index
    path("mysql/", include("mysqlapp.urls")),

    path('admin/', admin.site.urls),
]
  • mysqlapp > views.py
from django.shortcuts import render
from django.http import HttpResponse

### http ://127.0.0.1:8000/mysql/
def index(request) :
    return HttpResponse("<u>index 페이지입니다.</u>")
  • config > settiings.py에서 INSTALLED_APPS에 'mysqlapp' 추가

데이터 여러건 조회하기

  • templates\mysqlapp\cart\cart_list.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>장바구니 전체 목록 조회하기🧺</h2>
    <h5>조회 건수 : {{cart_cnt}}</h5>
    <table border="1">
      <tr>
        <th>회원아이디</th>
        <th>주문번호</th>
      </tr>
      {% for data in cart_list %}
      <tr>
        <th>{{ data.cart_member }}</th>
        <th>{{ data.cart_no }}</th>
      </tr>
      {% endfor %}
    </table>
  </body>
</html>
  • mysqlapp > views.py
from django.shortcuts import render
from django.http import HttpResponse

from mysqlapp.model.cart_model import Cart

### http ://127.0.0.1:8000/mysql/
def index(request) :
    return HttpResponse("index 페이지입니다.")

### 데이터 여러건 조회하기
# - 장바구니 리스트 조회하기
# - /mysql/cart_list/
def cart_list(request) :
    ### model(DB) 처리
    # Cart class 생성
    cart = Cart()
    
    ### 장바구니 전체 정보 조회하기
    # - cart_cnt : 정수값을 반환받음
    # - cart_list : [{'컬럼명' : 값, '컬럼명' : 값, ...}, {}, {}]
    cart_cnt, cart_list = cart.getCartList()
    
    ### 반환
    return render(
        request,
        "mysqlapp/cart/cart_list.html",
        {"cart_cnt" : cart_cnt,
         "cart_list" : cart_list}
    )
  • mysqlapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
     # http://127.0.0.1:8000/mysql/cart_list/
    path('cart_list/', views.cart_list ),
    # http://127.0.0.1:8000/mysql/
    path('', views.index ),
]

 

  • mysqlapp > model > model.py
    데이터와의 접속 정보를 담고, 커서 받아오기, 자원 종료 > 데이터베이스와 관련된 설정을 하는 곳
### 데이터베이스 처리 순서
# - DB 드라이버 연결 (PyMySQL이 연결 해줌)
# - DB 접속
# - DB로부터 cursor 받아오기
# - 조회/입력/수정/삭제 sql을 DB서버로 요청
# - DB 자원 반환

# - DB 드라이버 연결 (PyMySQL이 연결 해줌)
import pymysql

class Mysql_Model :
    ### 생성자
    def __init__(self) :
        # DB 접속 정보 정의
        self.initDBInfo()
        
        # DB 접속
        self.DBConnection()
        
        # DB로부터 cursor 받아오기
        self.DBCursor()
    
    ### DB 접속정보 확인
    def initDBInfo(self) :
        self.host = "localhost"
        self.user = "gjuser"
        self.password = "dbdb"
        self.db = "gjdb"
        # 문자 인코딩 타입
        self.charset = "utf8"
        # 조회 시 컬럼명을 동시에 보여줄지 여부 설정
        self.cursorclass = pymysql.cursors.DictCursor
        # 입력/수정/삭제 시 DB에 자동 반영 여부
        self.autocommit = True
        
    # - DB 접속
    def DBConnection(self) :
        try :
            self.conn = pymysql.connect(
                host = self.host,
                user = self.user,
                password = self.password,
                db = self.db,
                charset = self.charset,
                cursorclass = self.cursorclass,
                autocommit = self.autocommit
            )
            print("DB 접속 성공 -->", self.conn)
        except :
            print("DB 접속 정보 확인이 필요합니다.")
            
    # - DB로부터 cursor 받아오기
    def DBCursor(self) :
        self.cur = self.conn.cursor()
        
    # - 조회/입력/수정/삭제 sql을 DB서버로 요청
    # - cart_model.py에서 처리
    
    # - DB 자원 반환
    def DBClose(self) :
        try:
            self.cur.close()
            self.conn.close()
            print("DB 정보 반환 완료")
        except:
            print("이미 DB 정보가 반환되었습니다.")
  • mysqlapp > model > cart_model.py
    sql구문 작성
import pymysql
from mysqlapp.model.mysql import Mysql_Model

class Cart :
    ### 생성자
    def __init__(self) :
        self.db = Mysql_Model()
        
    ### 장바구니 전체 조회하기
    def getCartList(self) :
        sql = """
            Select cart_member, cart_no
            From cart
            Order By cart_member, cart_no        
        """
        
        ### DB에 요청하기 : cursor에 담기
        # 실행 결과의 건수
        rs_cnt = self.db.cur.execute(sql)
        
        # 실행 결과 데이터
        rows = self.db.cur.fetchall()
        
        # DB 정보 반환하기
        self.db.DBClose()
        
        return rs_cnt, rows

 

회원 상세정보 불러오기

  • templates\mysqlapp\cart\cart_list.html
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>회원 상세 조회하기😊</h2>
    <table border="1">
      <tr>
        <th>회원아이디</th>
        <td>{{mem_view.mem_id}}</td>
      </tr>
      <tr>
        <th>회원이름</th>
        <td>{{mem_view.mem_name}}</td>
      </tr>
      <tr>
        <th>회원주소</th>
        <td>{{mem_view.mem_add1}} {{mem_view.mem_add2}}</td>
      </tr>
    </table>
  </body>
</html>
  • mysqlapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/mysql/mem_view/
    path('mem_view/', views.mem_view ),
    
    # http://127.0.0.1:8000/mysql/cart_list/
    path('cart_list/', views.cart_list ),
    
    # http://127.0.0.1:8000/mysql/
    path('', views.index ),
]
  • mysqlapp > views.py
from django.shortcuts import render
from django.http import HttpResponse

from mysqlapp.model.member_model import Member

def mem_view(request) :
    ### 요청 파라메터 받기 : request가 가지고 있음
    if request.method == "POST" :
        mem_id = request.POST.get("mem_id", "none")
    elif request.method == "GET" :
        mem_id = request.GET.get("mem_id", "none")
        
        # DB 조회
        member = Member()
        rs_cnt, mem_view = member.getMemberView(mem_id)
        
    return render(
        request,
        "mysqlapp/member/mem_view.html",
        {"mem_view" : mem_view}
    )
  • mysqlapp > model > member_model.py
import pymysql
from mysqlapp.model.mysql import Mysql_Model

class Member :
    ### 생성자
    def __init__(self) :
        self.db = Mysql_Model()
        
    ### 회원 상세 조회하기
    def getMemberView(self, mem_id) :
        sql = f"""
            Select mem_id, mem_name, mem_add1, mem_add2
            From member   
            Where mem_id = '{mem_id}'  
        """
        
        ### DB에 요청하기 : cursor에 담기
        # 실행 결과의 건수
        rs_cnt = self.db.cur.execute(sql)
        
        # 실행 결과 데이터 
        # - {'컬럼명' : 값, '컬럼명' : 값, ...}
        # 한건 조회 이므로 fetchone
        row = self.db.cur.fetchone()
        
        # DB 정보 반환하기
        self.db.DBClose()
        
        return rs_cnt, row

728x90
반응형
728x90
반응형

Client - Server

client   server(WAS, Web Application Server) DB Server
브라우저
요청 url (http://127.0.0.1:8000/index)

요청(request)
web server

Container(Application)

    config라는 폴더의 djang App(ex. firstapp)
    Apache
넘어 온 주소 확인 후 index를 container로 넘김(즉, index 페이지 요청) →
Tomcat
index라는 이름의 pattern이 들어오면 특정 함수를 실행하라고 정의해 둠
이 함수는 java로 따지면 controller에 있는 함수. 
django로 따지면 views.py에 있는 함수
파싱(parsing)
html을 다시 읽어냄

응답(reponse)
html을 요청한 사람한테 넘김 함수가 실행되면서 html에 담긴 데이터를 web server로 다시 보내줌  

 

 

Django

  • Python 프레임워크 : Django, Flask 
  • 가상환경 새로 생성하여 진행
> conda create -n gj_django python=3.9
> conda activate gj_django
> pip install jupyter notebook
> python -m ipykernel install --user --name gj_django --display-name gj_django_kernel
> pip install ipython jupyter matplotlib pandas xlrd seaborn scikit-learn(python 버전 11이상이면 sklearn)
> pip install openpyxl
> conda install -c conda-forge django==4.0.1

Django 프로젝트 생성하기

  • Django 서버 생성
tutorial 파일로 이동
> django-admin startproject config . (config 한칸 띄우고 점. 찍기 > 현재 폴더에 config 폴더 생성 됨)

서버 테스트(웹은 생성시 마다 서버에 문제 없는지 확인 필요)
> python manage.py runserver

ctrl 누르고 아래 주소 클릭
> http://127.0.0.1:8000/

Django 페이지 등장🚀

Django VScode 설정 사항

  • vscode 실행 방법
    Prompt에서 가상환경 실행 후 totutorial 파일로 이동
(gj_django) C:\Users\user\gj_202311\11_Django\edu_django\tutorial>code .

 

  • config > settings.py 설
1. ALLOWED_HOSTS = [] 에 "127.0.0.1" 입력
결과 > ALLOWED_HOSTS = ["127.0.0.1"]

2. TEMPLATES에서 DIRS': []에 BASE_DIR/"templates" 입력
결과 > 'DIRS': [BASE_DIR/"templates"]

3. 언어 설정
> LANGUAGE_CODE = 'ko-kr'

4. 시간 설정
> TIME_ZONE = 'Asia/Seoul'

5. 파일 위치 설정
STATIC_URL = 'static/' 아래에
> STATICFILES_DIRS = [BASE_DIR/"static"] 추가

6. 나중에 사용할 부분

> INSTALLED_APPS
> DATABASES
 

  Web Site 만들기

  • firstapp 생성
Prompt tutoral 폴더 안에서 
> python manage.py startapp firstapp

영역을 app으로 나눠서 사용함 (ex. loginapp, joinapp)

  • firstapp 실행
INSTALLED_APPS 리스트에 'firstapp' 추가

  Web Site 만들기_함수

  • views.py
    앱의 시작점은 views.py (Spring으로 따지면 Controller에 해당)
from django.shortcuts import render

from django.http import HttpResponse

# Create your views here.
def index(request) :
    return HttpResponse("<u>firstapp의 index 페이지!!</u>")
  • urls.py
from django.contrib import admin
from django.urls import path
from firstapp import views as firstapp_view

urlpatterns = [
    ### http://127.0.0.1:8000/index
    path('index/', firstapp_view.index),

    path('admin/', admin.site.urls),
]

 

  Web Site 만들기_html

  • views.py
from django.shortcuts import render

from django.http import HttpResponse

# Create your views here.
def index(request) :
    return HttpResponse("<u>firstapp의 index 페이지!!</u>")

### http://127.0.0.1:8000/index_html
def indexHtml(request) :
    return render(
        request,
        "firstapp/index.html",
        {} # 어떤값을 줄건지 딕셔너리에 넣기
    )
  • templates\firstapp 파일 생성 후 index.html 작성
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>FirstApp-index.html</h2>
    <p>firstapp의 index.html 페이지 입니다.</p>
  </body>
</html>
  • urls.py
from django.contrib import admin
from django.urls import path
from firstapp import views as firstapp_view

urlpatterns = [
  
    ### http://127.0.0.1:8000/index
    path('index/', firstapp_view.index),
    
    ### http://127.0.0.1:8000/index_html
    path('index_html/', firstapp_view.indexHtml),

    path('admin/', admin.site.urls),
]

 

 

MainApp 생성

  •  mainapp 생성
Prompt tutoral 폴더 안에서 
> python manage.py startapp mainapp

INSTALLED_APPS 리스트에 'mainapp' 추가
  • view.py
from django.shortcuts import render

# Create your views here.

### http://127.0.0.1:8000/main_index
def index(requset) :
    return render(
        requset,
        "mainapp/index.html",
        {}
    )
  • templates\mainapp 파일 생성 후 index.html 작성
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>MainApp-index.html</h2>
    <p>mainapp의 index.html 페이지 입니다.</p>
  </body>
</html>
  • urls.py
from django.contrib import admin
from django.urls import path
from firstapp import views as firstapp_view
from mainapp import views as mainapp_view

urlpatterns = [
    ### http://127.0.0.1:8000/main_index
    path('', mainapp_view.index),
    
    ### http://127.0.0.1:8000/main_index
    path('main_index/', mainapp_view.index),
  
    ### http://127.0.0.1:8000/index
    path('index/', firstapp_view.index),
    
    ### http://127.0.0.1:8000/index_html
    path('index_html/', firstapp_view.indexHtml),

    path('admin/', admin.site.urls),
]

  • 설치 라이브러리
더보기

Python 관련

Python

Python Extension Pack

Python Extended

Python Indent

Python Debugger

Python snippetes

 

HTML, CSS, JS 관련

HTML CSS Support

HTML5 extension pack

html5-skelton

Extended Html5 Boilerplate

Html5 Reset Css

CSS Snippets

VS Code JavaScript (ES6) snippets

 

Django 관련

Django

Django Snippets

Django Templates

Django Snippets

 

url을 각 app에서 관리하게 하기 _firstapp

  • config에 있는 urls.py를 firstapp에 복사
  • config에 있는 urls.py
from django.contrib import admin
from django.urls import path, include
# from firstapp import views as firstapp_view
# from mainapp import views as mainapp_view

urlpatterns = [
    ### firstapp의 urls.py 사용하기
    # http://127.0.0.1:8000/first/index
    path("first/", include("firstapp.urls")),
    
    # ### http://127.0.0.1:8000/main_index
    # path('', mainapp_view.index),
    
    # ### http://127.0.0.1:8000/main_index
    # path('main_index/', mainapp_view.index),
  
    # ### http://127.0.0.1:8000/index
    # path('index/', firstapp_view.index),
    
    # ### http://127.0.0.1:8000/index_html
    # path('index_html/', firstapp_view.indexHtml),

    path('admin/', admin.site.urls),
]
  • firstapp에 있는 urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/index
    path('index/', views.indexHtml ),
    
    # http://127.0.0.1:8000/first/
    path('', views.indexHtml ),
]

 

url을 각 app에서 관리하게 하기 _mainapp

  • firstapp에 있는 urls.py를 firstapp에 복사
  • config에 있는 urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    ### firstapp의 urls.py 사용하기
    # http://127.0.0.1:8000/first/index
    path("first/", include("firstapp.urls")),
    
    ### mainapp의 urls.py 사용하기
    # http://127.0.0.1:8000/main/index
    path("main/", include("mainapp.urls")),

    path('admin/', admin.site.urls),
]
  • mainapp에 있는 urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/main/index
    path('index/', views.index ),
    
    # http://127.0.0.1:8000/main/
    path('', views.index ),
]

 

  • http://127.0.0.1:8000/ 만 입력 했을 때 main의 index가 뜨게 하는 방법
from django.contrib import admin
from django.urls import path, include
from mainapp import views as mainapp_view

urlpatterns = [
    ### firstapp의 urls.py 사용하기
    # http://127.0.0.1:8000/first/index
    path("first/", include("firstapp.urls")),
    
    ### mainapp의 urls.py 사용하기
    # http://127.0.0.1:8000/main/index
    path("main/", include("mainapp.urls")),
    
    # http://127.0.0.1:8000/
    path("", mainapp_view.index),
    path("index/", mainapp_view.index),
    
    path('admin/', admin.site.urls),
]

 

페이지 이동하기

  • mainapp > index.html (firstapp > index.html도 동일)
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>MainApp-index.html</h2>
    <p>mainapp의 index.html 페이지 입니다.</p>
    <p>
      <a href="/first/">firstapp/index 바로가기</a>
    </p>
  </body>
</html>

클릭 시 해당 페이지로 이동

 

이미지 삽입하기

  • firstapp > static\firstapp > images 생성
  • firstapp의 index.html
    {% load static %} > static 폴더를 사용하겠다는 의미
{% load static %}
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>FirstApp-index.html</h2>
    <p>firstapp의 index.html 페이지 입니다.</p>
    <p>
      <a href="/main/">Home 바로가기</a>
    </p>
    <p>
      <img
        src="{% static '/firstapp/images/fashion739.jpg' %}"
        width="300"
        height="300"
      />
    </p>
  </body>
</html>

  • 이미지 안불러와지면 settings.py에 가서 / 앞뒤로 띄어쓰기 한번 씩 하기 
STATICFILES_DIRS = [BASE_DIR / "static"]

 

jupyter 파일 웹에 적용하기_파일 생성해서 불러오기

  • 방법
    1. jupyter 에 있는 파일을 파이썬으로 저장
    2. firstapp에 ml_view 폴더 생성 후 안에 파이썬으로 저장한 파일 넣기
    3. 파이썬 내용 함수로 감싸기
  • firstapp > ml_view > ml_view.py 생성(여기 안에서는 항상 함수로 진행)
  • firstapp > ml_view.py
def getView() :
    ### 이미지 처리 수행 후
    ### 이미지를 static 위치에 저장까지만 하면 됨
    # - return은 안해도 됨. 테스트를 위해
    return "test"
  • firstapp > views.py
from firstapp.ml_view import ml_view

### http://127.0.0.1:8000/first/ml_view
def ml_View(request) :
    ### getView() 함수 호출하기
    rs_data = ml_view.getView()
    
    return render(
        request,
        "firstapp/ml_view/ml_view.html",
        {"rs_data" : rs_data}
    )
  • templates\firstapp > ml_view > ml_view.html 생성
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>ML-View 페이지</h2>
    <p>받아온 값 rs_data ={{rs_data}}</p>
  </body>
</html>
  • firstapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/ml_view/
    path('ml_view/', views.ml_View ),
]

 

jupyter 파일 웹에 적용하기_기존 py 파일(Class) 사용하기

  • data_view.py 파일 사용
    그래프 저장 위치 변경하기

  • firstapp > views.py
from firstapp.data_view.data_view import Data_View

### http://127.0.0.1:8000/first/data_view/
def data_View(request) :
    ### Data_View 클래스 호출하기
    data_view = Data_View()
    
    return render(
        request,
        "firstapp/data_view/data_view.html",
        {}
    )
  • templates\firstapp > data_view > data_view.html 생성
{% load static %}
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>FirstApp - index.html</title>
  </head>
  <body>
    <h2>Data-View 페이지</h2>
    <p>
      <img
        src="{% static '/firstapp/images/fig.png' %}"
        width="300"
        height="300"
      />
    </p>
  </body>
</html>
  • firstapp > views.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/data_view/
    path('data_view/', views.data_View ),
]

model 웹에 적용하기

  • model_view.py 파일 사용
    데이터 읽어들이기 / 훈련모델 저장시키기 / 훈련모델 불러오기 파일 경로 변경하기
  • firstapp > views.py
from firstapp.model_view.ml_view import ML_View

### http://127.0.0.1:8000/first/model_view/
def model_View(request) :
    ### ML_View 클래스 호출하기
    ml_view = ML_View()
    
    ### 정확도
    score = ml_view.getModelScore()
    
    ### 예측하기
    # 사용할 예측 데이터
    # - [[200.0, 23.0, 25.8, 10.34, 3.66]]
    x_input = [[200.0, 23.0, 25.8, 10.34, 3.66]]
    pred_data = ml_view.getModelPredict(x_input)
    
    return render(
        request,
        "firstapp/data_view/data_view.html",
        {"score" : score,
         "pred_data" : pred_data}
    )
  • templates\firstapp > model_view > model_view.html 생성
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>Model-View 페이지</h2>
    <p>정확도 : {{score}}</p>
    <p>예측 : {{pred_data}}</p>
  </body>
</html>
  • firstapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/model_view/
    path('model_view/', views.model_View ),
]

지도 웹에 적용하기

  • map_view.py 데이터 사용
    데이터 읽어들이기 파일 경로 변경하기
    folium 라이브러리 설치
  • firstapp > views.py
from firstapp.map_view.map_view import Map_View

### http://127.0.0.1:8000/first/map_view/
def map_View(request) :
    ### Map_View 클래스 호출하기
    map_view = Map_View()
    
    ### 지도 결과를 html로 받아오기
    map_html = map_view.getMapHtml() 
    
    ### 지도 시각화에 사용한 데이터 프레임 받아오기
    
    map_data = map_view.getDataFrame()
    
    return render(
        request,
        "firstapp/map_view/map_view.html",
        {
          "map_html" : map_html,
            "map_data" : map_data.to_html(),
         }
    )
  • templates\firstapp > map_view > map_view.html 생성
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>Map-View 페이지</h2>
    <p>{{map_html | safe}}</p>
    <p>{{map_data | safe}}</p>
  </body>
</html>
  • firstapp > urls.py
from django.urls import path
from . import views

urlpatterns = [
    # http://127.0.0.1:8000/first/map_view/
    path('map_view/', views.map_View ),
]

728x90
반응형
728x90
반응형

페이스북 시계열 분석 라이브러리 : Prophet

📍 시계열 예측을 그래프(시각화)로 표현하는 모델
📍 Prophet 모델에 넣어줘야 하는 데이터 형태
- index는 날짜, Data컬럼, Adj Close(수정종가) 컬럼
- Prophet에서 사용하는 컬럼명은 ds, y 컬럼명을 사용함
     > 기존 컬럼명을 수정해야함
     > Data 컬럼명은 ds로, Adj Close 컬럼명은 y로 수정

데이터 프레임 수정

### 원본데이터에서
# - 최종 데이터 프레임 변수명 : prophet_data
prophet_data = goog_data.copy()

# - Date index는 컬럼 데이터로 변환
prophet_data.reset_index(inplace=True)

# - 훈련에 사용할 컬럼명 : Date, Adj Close
# - 훈련에 사용하지 않는 컬럼은 삭제
prophet_data.drop(["Open", "High", "Low", "Close", "Volume"], axis=1, inplace=True)

# - 훈련에 사용할 컬럼명 변경 : Data > ds, Adj Close > y
prophet_data.columns = ['ds', 'y']

# - ds 데이터 타입 변경
prophet_data["ds"] = pd.to_datetime(prophet_data["ds"])
prophet_data

 

 

Prophet 라이브러리 설치

📍Prophet 라이브러리 
- 가상환경 새로 만들어서 진행 : 버전 충돌이 많이 일어남
- 가상환경 생성 시 python 버전은 3.6 버전 사용(3.9 버전은 사용이 안되기에, 3.9 이하 버전으로 사용)
- Prophet 라이브러리는 C++ 프로그램으로 만들어져 있음
from fbprophet import Prophet

 

Prophet 모델 생성

''' 일 단위 주기성 활성화하기 '''
### prophet 모델 생성
model = Prophet(daily_seasonality=True)

''' 모델 학습 시키기 '''
model.fit(prophet_data[["ds", "y"]].iloc[:-10])

 

3년 후 예측하기

### 기존 값에 3년 후 일자를 포함해서 추출하기
future = model.make_future_dataframe(periods=365 * 3)
# future

### 예측하기
forecast = model.predict(future)
# forecast

### 시각화
model.plot(forecast)

 

# 계절성을 나타내는 그래프 
# 그려진 범위 그래프가 커질 수록 오차가 있는 것
model.plot_components(forecast)

 

728x90
반응형
728x90
반응형

시계열 분석 주식 데이터_주가 예측

https://mzero.tistory.com/146 에 이어서

 

[시계열 분석] 주가예측 / 시계열 데이터 분석 / ARIMA 모델

시계열 분석 주식 데이터_주가 예측 ''' 기본 라이브러리 ''' import datetime import matplotlib.pyplot as plt import platform from matplotlib import font_manager, rc ''' 마이너스 기호 및 한글 설정 ''' ### 마이너스 기호 사

mzero.tistory.com

 

Best Model을 이용해서 잔차 확인

📍 잔차 : 실제값과 예측값과의 차이
📍 잔차 검정 : 정상성, 정규성 등을 만족하는지 확인하는 검정
📍 검정하는 함수 : summary(), plot_diagnostics()
  • summary()

 

확인해야할 사항

Heteroskedasticity (H) : 값이 작을수록 정규분표

P>|z| : p-value 값으로 유의미한지, 아닌지 판단

 

 

 

 

 

 

 

 

 

 

  • plot_diagnostics()
    model.plot_diagnostics(figsize=(16, 8))
    plt.show()

 

3번 그래프 : 빨간색 추세선과 비슷하게 흘러가는 것이 좋음

4번 그래프 : 0을 기점으로 모두 포함 되어 있어서 정상성을 띔, 차수의 첫번 째는 계산이 안되기 때문에 0은 빠짐

 

정상성을 띄지만, 정규분포는 낮다

 

 

 

ARIMA 모델 훈련 및 테스트하기

  • 훈련 및 테스트 데이터 = 9 : 1 로 분리
    - 시계열 데이터는 train_test_split()함수를 사용하지 않는다.
    -연속성을 띄는 데이터의 특성상, 데이터를 앞/뒤의 비율로 분리한다.
    train_data = data[:int(len(data) * 0.9)]
    test_data = data[int(len(data) * 0.9):]
    
    train_data.shape, test_data.shape​


  • auto_arima : 모델 설정 및 Best Model 추출
    - auto_arima는 훈련과 동시에 베스트 모델을 생성해 준다.
    model_fit = pm.auto_arima(
        y=train_data,
        d=n_diffs,
        start_p=0, max_p=3,
        start_q=0, max_q=3,
        m=1, seasonal=False,
        stepwise=True,
        trace=True
    )​


Best Model을 이용하여 예측(Predict)하기

📍 시계열에서 예측 용어 : forecast라고 칭한다.
📍 예측 결과 : 예측데이터, 상한가(상한 바운드), 하한가(하한 바운드)
📍 결과 시각화 : 기존값과 예측값이 연결된 시각화
📍 수행방법 : forecast 함수 생성 후 predict 수행 > 예측결과 반환

 

  • 함수 생성하기
    import numpy as np
    
    """향후 예측
     - model : Best Model
     - n : 예측하려는 향후 기간 (디폴트로 1을 지정했음)
    """
    def forecast_n_step(model, n=1):
        ### 예측하기
        # - n_periods : 예측기간 (day일단위)
        # - return_conf_int : 신뢰구간 반환여부
        # - fc : 예측결과(y_pred)
        # - conf_int : 신뢰구간
        fc, conf_int = model.predict(n_periods=n, return_conf_int=True)
        
        # print(fc, conf_int)
        ### 반환값은 리스트형태로 변환해서 전달
        return (
            fc.tolist()[0:n],
            # asarray : 배열로 바꾸는 함수 / tolist : 리스트로 바꾸는 함수
            np.asarray(conf_int).tolist()[0:n]
        )

    """함수 생성하기"""
    import pandas as pd
    
    def forecast(len, model, index, data=None) :
        ### 결과값을 담아서 반환할 변수
        y_pred = []
        pred_upper = []
        pred_lower = []
    
        ###데이터(data)가 있는 경우
        if data is not None :
            for new_data in data :
                ### 예측하기 : 반복수행을 위해 함수로 생성
                fc, conf = forecast_n_step(model)
    
                ### 예측결과 리스트에 담기
                y_pred.append(fc[0])
    
                ### 상한가
                pred_upper.append(conf[0][1])
    
                ### 하한가
                pred_lower.append(conf[0][0])
    
                ### 시계열에서는 데이터별로 Model을 갱신함
                model.update(new_data)
                
        
        ###데이터(data)가 없는 경우
        else : 
            for i in range(len):
                fc, conf = forecast_n_step(model)
                
                ### 예측결과 리스트에 담기
                y_pred.append(fc[0])
    
                ### 상한가
                pred_upper.append(conf[0][1])
    
                ### 하한가
                pred_lower.append(conf[0][0])
    
                ### 시계열에서는 데이터별로 Model을 갱신함
                model.update(fc[0])
            
    
        ### 결과값에 대해서는 시리즈 타입으로
        return pd.Series(y_pred, index=index), pred_upper, pred_lower
        # return "", "", ""
  • 함수 호출하기
    '''
    함수 호출하기
     - fc : 예측결과
     - upper : 상한가
     - lower : 하한가
    '''
    
    fc, upper, lower = forecast(len(test_data), model_fit,
                               test_data.index, data=test_data)
    fc, upper, lower


  • 상한가와 하한가의 리스트 타입 데이터를 날짜를 인덱스로 하는 시리즈 타입으로 변환하기
     - 추후 시각화 시 결과값의 인덱스와 매핑하여 그리기 위함

    lower_series = pd.Series(lower, index=test_data.index)
    upper_series = pd.Series(upper, index=test_data.index)
    
    lower_series, upper_series​


  • 전체 시각화
    - 훈련데이터 및 테스트데이터 시각화
    plt.figure(figsize=(20, 6))
    plt.title("시계열 분석 결과 시각화")
    
    ### 훈련데이터 그리기
    plt.plot(train_data, label="train_data")
    
    ### 테스트 데이터 그리기
    plt.plot(test_data, label="test_data(예측 전 실제값)", c="b")
    
    ### 테스트데이터로 예측한 결과 그리기
    plt.plot(fc, label="예측결과", c="r")
    
    ### 상한가(상한 바운드) 하한가(하한 바운드) 그리기
    plt.fill_between(lower_series.index, lower_series,
                    upper_series, alpha=.9, color="k")
    
    plt.legend()
    plt.show()​

모델 성능 평가

from sklearn.metrics import mean_absolute_error, mean_squared_error
import math
  • 평균제곱오차(MSE)
    mse =  mean_squared_error(np.exp(test_data), np.exp(fc))
    mse​


  • 평균절대오차(MAE)
    mae =  mean_absolute_error(np.exp(test_data), np.exp(fc))
    mae​


  • RMSE(Root Mean Squared Error)
    - 예측값과 실제값 간의 거리를 나타내는 지표
    - 값이 작을 수록 모델의 성능이 좋다고 해석 
    rmse = math.sqrt(mean_squared_error(np.exp(test_data), np.exp(fc)))
    rmse​


  • MAPE(Mean Absolute Percentage Error)
    - 예측값과 실제값 간의 백분율 오차 평균
    mape = np.mean(np.abs(np.exp(fc) - np.exp(test_data)) / np.abs(np.exp(test_data)))
    mape * 100​


한국 증권거래소(KRX)의 주식거래일을 기준으로 1년 후 예측하기

  • 사용 라이브러리 
     - 한국증권거래소(KRX)의 주식거래일자에 대한 데이터 수집을 위한 라이브러리
     - 설치 필요 : pip install exchange_calendars
    import exchange_calendars as ecals​
  • 주식 거래일자 수집하기
    ### 원본 인덱스의 마지막 인덱스 일자 이후부터 1년치에 대한 거래일자 수집
    # 거래 시작일
    start = "2022-11-01"
    # 거래 종료일
    end = "2023-10-31"
    
    ### 한국증권거래소(KRX) code 값 : XKRX
    k = ecals.get_calendar("XKRX")
    k​


  • 시작 및 종료 기간 동안의 거래일 정보 가지고 오기 
    df =pd.DataFrame(k.schedule.loc[start:end])
    df



  • open 컬럼을 사용하기 위해 날짜 정보를 리스트에 추가하기
    date_list = []
    for i in df["open"] :
        date_list.append(i.strftime("%Y-%m-%d"))
        # print(i.strftime("%Y-%m-%d"))
    
    ### DatetimeIndex 형태로 변환하기
    date_index = pd.DatetimeIndex(date_list)
    date_index


  • 1년 후 주가 예측하기
    fc2, upper2, lower2 =forecast(len(date_index), model_fit, date_index)
    fc2


  • 상한가와 하한가의 리스트 타입 데이터를 날짜를 인덱스로 하는 시리즈 타입으로 변환하기
    - 추후 시각화 시 결과값의 인덱스와 매핑하여 그리기 위함
    lower2_series = pd.Series(lower2, index=date_index)
    upper2_series = pd.Series(upper2, index=date_index)
    
    lower2_series, upper2_series​
  • 훈련데이터 및 테스트데이터 시각화
    plt.figure(figsize=(20, 6))
    plt.title("[1년 후] 시계열 분석 결과 시각화")
    
    ### 훈련데이터 그리기
    plt.plot(train_data, label="train_data")
    
    ### 테스트 데이터 그리기
    plt.plot(test_data, label="test_data(예측 전 실제값)", c="b")
    
    ### 테스트데이터로 예측한 결과 그리기
    plt.plot(fc, label="예측결과", c="r")
    
    ### 1년 후 주가 예측 그리기
    plt.plot(fc2, label="1년 후 예측결과", c="g")
    
    ### 테스트 데이터 예측 > 상한가(상한 바운드) 하한가(하한 바운드) 그리기
    plt.fill_between(lower_series.index, lower_series,
                    upper_series, alpha=.9, color="k")
    
    ### 1년 후 예측 > 상한가(상한 바운드) 하한가(하한 바운드) 그리기
    plt.fill_between(lower2_series.index, lower2_series,
                    upper2_series, alpha=.9, color="k")
    
    plt.legend(loc="upper left")
    plt.show()
728x90
반응형
728x90
반응형

시계열 분석 주식 데이터_주가 예측

''' 기본 라이브러리 '''
import datetime
import matplotlib.pyplot as plt

import platform
from matplotlib import font_manager, rc

''' 마이너스 기호 및 한글 설정 '''
### 마이너스 기호 사용 설정
plt.rcParams["axes.unicode_minus"] = False
### OS 별 한글 설정
if platform.system() == "Windows" :
    path = "c:/Windows/Fonts/malgun.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc("font", family=font_name)

### Mac인 경우
elif platform.system() == "Darwin" :
    rc("font", family="Applegothic")

### 리눅스인 경우
elif platform.system() == "Linux" :
    path = "/usr/share/fonts/NanumGothic.ttf"
    font_name = font_manager.FontProperties(fname=path).get_name()
    rc("font", family="font_name")

else :
    print("OS 확인 불가")

10년 치 주가 정보 수집하기

📍 증권사 : yahoo finance
📍 수집 증권 : 구글 주식(GOOG) 수집 
📍 수집 기간 : 2012년 10월 31일부터 2022년 10월 31일까지 데이터 
📍 증권사 제공 라이브러리 : yfinance 라이브러리를 제공하고 있음
📍 라이브러리 설치 필요 pip install yfinance
import yfinance as yf

 

  • 데이터 수집하기
    - 시작 및 종료 기간 변수 설정
    - 날짜 타입으로 넣어야 함
    start = datetime.datetime(2012, 10, 31)
    end = datetime.datetime(2022, 10, 31)
    start, end​


  • Google(GOOG) 주식 가격 데이터 가져오기
    - 첫 번째 인자 : 가져올 주식(증권) 지정

    - start : 거래 시작일
    - end : 거래 종료일
    goog_data = yf.download("GOOG", start=start, end=end)
    goog_data​
     

 

 

 - index : 날짜 타입
 - Open : 시작가
 - High : 상한가
 - Low : 하한가
 - Close : 종가
 - Adj Close : 수정종가(분할, 배당, 배분, 신주 등이 발생한 경우 조정이 이루어짐)
 - Volume : 거래량

 

  • 전처리
    - 수정 종가 데이터만 추출하기

    data = goog_data["Adj Close"]
    data​

주식흐름(Rolling) 확인하기

📍주식 흐름
- 흐름 또는 이동이라고 칭하며, 롤링(rolling)이라는 명칭을 사용한다.
- 주식 흐름을 확인하기 위해서는 이동(rolling) 평균과 이동(rolling) 표준편차 데이터가 필요하다.
  • 50일 치에 대한 주식흐름(이동 흐름) 확인하기
    - 50일치에 이동(rolling) 평균과 표준편차 계산하기
    ### 기간 설정 : 50일
    interval = 50
    
    ### 이동평균 계산하기
    # - 주식 가격의 흐름을 유연성을 높이고 보기 좋게 하기 위해서 사용
    # - 실제 가격 흐름과 이동평균값과 차이가 보이는 부분 : 변동성이 있는 부분
    rolmean = data.rolling(interval).mean()
    rolmean
    
    ### 이동표준편차 계산하기 : 변동성의 흐름 데이
    rolstd = data.rolling(interval).std()
    rolstd


  • 원본, 이동평균, 이동평균표준편차 시각화
plt.figure(figsize=(10, 6))
plt.title("실제, 이동평균, 이동표준편차 시각화")

### 실제 주식가격 그리기
plt.plot(data, color="blue", label="실제 원본 주가")

### 50일 간격의 이동평균 그리기
plt.plot(rolmean, color="red", label=f"이동평균 {interval}일 기준")

### 50일 간격의 이동표준편차 그리기
plt.plot(rolstd, color="green", label=f"이동평균표준편차 {interval}일 기준")

plt.xlabel("Date")
plt.ylabel("best")

plt.legend()

plt.show()​

 

<시각화 해석>
* 비정상성 : 평균이 일정하지 않고 오르락내리락하는 불규칙 형태를 의미함
 - 시계열 분석 시에는 비정상성을 정상성으로 만들어서 분석을 진행한다.
- 정상성으로 만들기 위해 차수(d)라는 개념이 적용됨

- 표준화(정규화) 시키는 개념과 유사함
- 계절성을 나타내지 않는 것으로 보이며, 특징적 패턴을 보이고 있지 않음(=특정 주기성이 없음)

 

시계열 데이터 분석 모델 - ARIMA 모델

📍 시계열 분석
- 시계열 분석에서 주로 사용되는 모델은 ARIMA 모델로 오랫동안 사용되어 온 통계학적 기술통계 모델이다.
- 시계열 분석은 일반적으로 예측분석 중에서도 시간을 독립변수(X)로 사용하고, 다른 데이터를 종속변수(Y)로 사용하여 예측하는 분석 방법 이다.

📍 ARIMA(Autoregressive Integrated Moving Average)
- 시계열 분석(예측)에서 가장 널리 사용되는 모델 중 하나
- 시계열 분석은 현 시점까지의 데이터를 이용해서 앞으로 어떤 패턴의 차트를 그릴지 예측하는 분석기법이다.

 * AR(Autoregressive) : "자기상관" 이라고 칭한다.
 - 이전의 값이 이후의 값에 영향을 미치고 있는 상황(관계)

 * MA(Moving Average) : "이동평균"이라고 칭한다.
 - 특정 변수의 평균값이 지속적으로 증가한거나 감소하는 추세(추이)

📍 정상성(stationary)과 비정상성(Non-stationary)
 * 정상성
    - 평균과 분산이 일정한 형태

 * 비정상성
    - 평균과 분산이 일정하지 않은 형태
    - 시간에 따라 평균 수준이 다르거나, 특징적 패턴(Trend)이나 계절성(Seasonality)에 영향을 받는 형태
    - 예시 데이터 형태 : 겨울에 난방비 증가, 여름에 아이스크림 판매량 증가 등

   - 비정상성 데이터는 예측 범위가 너무 다양하고 많기 때문에 고려해야할 특성들이 많다.
    - 이에, 비정상성 데이터를 정상성으로 변환하여 분석을 진행한다.
    - 정상성으로 분석을 진행하며, 예측범위가 일정하게 줄어들고, 성능이 개선되는 효과를 발휘함

📍 비정상성을 정상성으로 변환하는 방법들
 - 평균의 정상화를 위한 차분 사용
 - 분산의 안정화를 위한 로그 변환 사용
 - 제곱/제곱근 변환 가용
 - 이외

 * 차분 : 비정상성을 정상성으로 만들기 위해 관측값들의 차이를 계산하여 사용하게 됨

 

시계열 정상성 확인하기 - ADF 테스트

📍  ADF 테스트(Augmented Dickey-Fuller Test)
- 시계열 데이터의 정상성 여부를 통계적인 정량 방법으로 검증하는 방법
- 귀무가설과 대립가설에 따라 결정됨
- 귀무가설 : 기존 연구이론
 - 대립가설 : 신규 연구이론(우리가 하고자 하는 것)
 - 귀무가설과 대립가설의 보편적 기준 > p-value < 0.05(증감 가능)
     : p-value < 0.05이면, 귀무가설 기각, 대립가설 채택
     : p-value > 0.05이면, 귀무가설 채택(연구 방향을 수정해야 함)
 - 시계열 분석에서는 정상성과 비정상성 데이터의 형태를 구분하는 용도로 사용됨
 - ADF 테스트 라이브러리 : statsmodels 패키지의 dfuller 라이브러리 사용
''' ADF 라이브러리 '''
from statsmodels.tsa.stattools import adfuller

''' 원본(수정종가) 데이터를 이용해서 ADF 테스트 하기 '''
result = adfuller(data.values)
result

 

  • p-value 추출하기
    - ADF 결과의 1번째 값이 > p-value 값임
    print(f"p-value : {result[1]}")​

    💡 해석
     - p-value < 0.05을 만족하지 않으므로, 귀무가설을 기각 할 수 없음. 즉, 유의미 하지 않음
     - 따라서, 구글 주식 데이터는 "비정상성" 데이터이며, 정상성으로 만들기 위한 차분 처리가 필요함
     - p-value의 값이 0.827로 0.05보다 크므로... << 이렇게 작성하면 안됨

  • 1d(1차) 차분 계산하기
     - 1d(1차) : 1칸씩 이동하면서 이전과 현재의 차이값을 사용함
     - 사용함수 : diff()
     - 차분을 계산하게되면, 최초 또는 [차분의 이동 거리]에 따라서 Nan이 발생
         > Nan은 제거하고 사용함
    dff1 = data.diff().dropna()
    dff1


  • 차분 결과 데이터 시각화 하기
    dff1.plot(figsize=(15, 5))
    plt.title("차분 결과 데이터 시각화")
    plt.show()


  • 차분 결과 데이터를 이용하여 정상성 여부 확인하기
    - ADF 테스트 하여, p-value < 0.05 확인하기
    result = adfuller(dff1.values)
    print(f"p-value : {result[1]}")
    print("p-value : %f" % result[1])

    💡 해석
     - p-value < 0.05을 만족하므로, 유의미하다.
     - 즉, 귀무가설을 기각하고 대립가설을 채택
     - 시계열 분석에서는 차분 처리를 통해 정상성 데이터로 변환되었으며,
     - 이후, ARIMA 분석을 통해 진행이 가능한 것으로 증명 되었음
     - 사용된 차분은 1차 차분을 수행하여 증명하였음

  • 차분 설명 이미지
    - 차분을 할수록 정상성을 띄게 됨

    - 그러나 너무 많은 차분은 오히려 비정상성을 띄게 할 수 있음
    - 적절한 차수를 찾아서 차분을 진행해야 함(= 하이퍼파라미터 조정)

 

ARIMA 모델의 모수(하이퍼파라미터 찾기)

📍  ARIMA 모델에서 사용되는 중요한 3개의 하이퍼파라미터
- p, d, q
- ARIMA(AR, MA, ARMA) 모델을 사용하기 위해서는 AR(자기회귀모형, p), 차분(d), MA(이동평균모형, q) 값을 결정해야 함

📍 결정 방법
1. ACF plot과 PACF plot을 통해 모수(하이퍼파라메터)를 결정할 수 있음
     → 현재 값이 과거 값과 어떤 관계(relationship)가 있는지를 보여주는 그래프로 확인
2. pmdarima 라이브러리의 ndiffs, auto_arima 함수를 사용하여 모수(하이퍼파라미터) 결정할 수 있음  
     → 주로 auto_arima 함수를 사용함
  • (방법 - 1)  ACF plot과 PACF plot을 통해 모수(하이퍼파라메터)를 결정
    ''' 사용 라이브러리 '''
    from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
    
    ''' 실제 원본 데이터를 이용해서 > ACF 및 PACF 시각화 하기 '''
    plot_acf(data)
    plot_pacf(data)
    plt.show()

💡 해석

< ACF plot >
 - ACF plot에서 막대그래프가 천천히 감소되는 것으로 보임
 - 이는 주식 데이터가 주기에 따라 일정하지 않은 비정상 데이터로 판단한다.

< PACF plot >
 - 첫값을 제외한 1개 이후 파란 박스에 들어가면서, 막대 그래프가 끊기는 것으로 보임
 - 이는 자기회귀모형(AR)의 결과값이 1개 이후인, 즉 p는 1인 값을 활용하는 것이 적절하다는 의미임
 - 이동평균(MA)의 값은 AR과의 차이값이 0이 되도록 하는 것이 일반적임
 - 따라서, MA는 1이 적절함을 의미함

 

  • (방법 - 1)  1차 차분데이터로 ACF 및 PACF 시각화 하기
    plot_acf(dff1)
    plot_pacf(dff1)
    plt.show()

📍 결론
- AR(p) = 1, d = 1, MA(q) = 1이 적절
- 이때, MA(q)값은 AR - MA값을 사용하기도 한다. (q=0) - MA값은 AR - MA를 사용

 

  • (방법 - 2) pmdarima 라이브러리의 ndiffs, auto_arima 함수를 사용하여 모수(하이퍼파라미터) 결정
  • (방법 - 2) ndiffs 함수
    '''
    사용 라이브러리
    - 라이브러리 설치해야함 : pip install pmdarima
    '''
    import pmdarima as pm
    from pmdarima.arima import ndiffs
    
    '''
    ndiffs 방법 : 차수를 결정하는 함수
     - data : 원본 데이터
     - alpha : 차분 횟수를 결정하는데 사용할 p-value(유의수준)
     - test : 차분 획수를 결정하는데 사용할 테스트 방법
            : 주로 adf 테스트 방법을 사용 (kpss 테스트 방법도 있으나, 거의 사용안함)
     - max_d : 최대 차분 횟수를 제한함(이 범위 내에서 가장 적절한 차수를 결정)
    '''
    n_diffs = ndiffs(data, alpha=0.05, test="adf", max_d=6)
    print(f"결정된 차수 : {n_diffs}")​


  • (방법 - 2) auto_arima 함수
    - auto_arima 함수 사용 : p, d, q 값을 모두 추출해 준다.
    - y = 데이터 원본
    - d = 차분의 차수, 이를 지정하지 않으면 실행 시간이 매우 길어짐(기본값 None)
    - start_p(기본값 2), max_p(기본값 5) : AR(p)를 찾기 위함 범위(start_p에서 max_p까지 수행)
    - start_q(기본값 2), max_q(기본값 5) : AR(q)를 찾기 위함 범위(start_q에서 max_q까지 수행)
    - m : 계절적 특성이 있을 때 사용하는 매개변수(기본값 1) > 차수를 의미함
     - seasonal : 계절성 특성이 있을 때 사용(기본값 True)
                      : 계절성 특성이 있을 때 (True) > m의 값은 계절적 특성의 범위 차수 지정(보통 3)
                      : 계절성 특성이 없을 때 (False) > m은 1을 보통 사용
    - stepwise : 최적의 모수를 찾기 위한 알고리즘을 사용할지 여부
                       (최적의 모수 찾기 알고리즘 : 힌드만-칸다카르 알고리즘이 적용됨)
    - trace : 결과 출력 여부(기본값 False)
    model = pm.auto_arima(
        y=data,
        d=1,
        start_p=0, max_p=3,
        start_q=0, max_q=3,
        m=1, seasonal=False,
        stepwise=True,
        trace=True
    )

💡 해석

 - auto_arima를 사용한 결과에서 최적의 모델은 ARIMA(1,1,0)모형으로 결정됨
 - 모델의 설명력(결정력)이 좋을 수록 AIC 값이 작아지고,
 - 모델의 복잡도가 높아질수록 AIC값이 커짐            
 - AIC 값은 작을 수록 좋음

728x90
반응형

+ Recent posts