728x90
Obsidian Self-hosted LiveSync를 선택한 이유와 설정 순서

Obsidian Self-hosted LiveSync를 선택한 이유와 설정 순서

Obsidian을 NAS와 함께 사용할 때 여러 동기화 방법이 있지만, 저는 Self-hosted LiveSync 방식을 선택했습니다.

이유는 단순합니다. 여러 기기에서 Obsidian을 자주 사용한다면 단순 파일 동기화보다 실시간에 가까운 동기화 경험이 더 편하기 때문입니다.

Self-hosted LiveSync를 선택한 이유

1. 여러 기기 동기화에 유리함

Self-hosted LiveSync는 PC, 노트북, 스마트폰, 태블릿처럼 여러 기기에서 Obsidian을 사용할 때 좋습니다.

한 기기에서 작성한 노트가 다른 기기에도 비교적 빠르게 반영됩니다.

2. NAS를 직접 활용할 수 있음

Self-hosted LiveSync는 보통 CouchDB를 서버로 사용합니다.

NAS에 CouchDB Docker 컨테이너를 설치하면 Obsidian 동기화 서버를 직접 운영할 수 있습니다.

이번 설정에서는 NAS에 설치한 Docker 컨테이너 이름을 아래와 같이 사용합니다.

oleduc-docker-obsidian-livesync-couchdb-container

즉, Obsidian 노트 동기화 데이터는 외부 클라우드가 아니라 NAS에서 실행 중인 CouchDB 컨테이너에 저장됩니다.

3. Obsidian Sync 대체용으로 좋음

Obsidian 공식 Sync는 편리하지만 유료입니다.

Self-hosted LiveSync는 초기 설정이 조금 어렵지만, 한 번 구축해두면 직접 운영하는 Obsidian Sync처럼 사용할 수 있습니다.

4. 충돌 관리에 비교적 강함

단순 파일 복사 방식은 여러 기기에서 동시에 수정할 때 충돌이 생기기 쉽습니다.

Self-hosted LiveSync는 변경 이력을 기반으로 동기화하기 때문에 일반 WebDAV 동기화보다 여러 기기 사용에 더 적합합니다.

전체 설정 흐름

Self-hosted LiveSync 설정은 크게 다음 순서로 진행합니다.

NAS에 CouchDB Docker 컨테이너 준비
-> CouchDB 접속 확인
-> Obsidian에 Self-hosted LiveSync 설치
-> 첫 번째 기기 연결
-> 다른 기기 연결
-> 동기화 테스트

1. NAS에서 CouchDB Docker 컨테이너 확인하기

NAS에서 Docker 또는 Container Manager를 실행합니다.

설치된 컨테이너 목록에서 아래 컨테이너가 실행 중인지 확인합니다.

oleduc-docker-obsidian-livesync-couchdb-container

컨테이너 상태가 Running 또는 실행 중으로 표시되어야 합니다.

만약 중지되어 있다면 컨테이너를 시작합니다.

컨테이너 선택 -> 시작

2. CouchDB 접속 정보 확인하기

Self-hosted LiveSync에서 사용할 CouchDB 접속 정보가 필요합니다.

기본적으로 확인해야 할 항목은 다음과 같습니다.

CouchDB 주소: http://NAS주소:5984
사용자 이름: CouchDB 계정
비밀번호: CouchDB 비밀번호
데이터베이스 이름: obsidiannotes

예시는 다음과 같습니다.

Server URI: http://192.168.0.10:5984
Database Name: obsidiannotes
Username: admin
Password: 설정한 비밀번호

여기서 NAS주소는 본인 NAS의 내부 IP 주소나 도메인으로 바꾸면 됩니다.

외부에서도 사용할 예정이라면 HTTPS가 적용된 도메인을 사용하는 것이 좋습니다.

https://sync.example.com

3. CouchDB 접속 테스트하기

브라우저에서 아래 주소로 접속합니다.

http://NAS주소:5984

정상적으로 설정되어 있다면 CouchDB 응답 화면이 표시됩니다.

또는 로그인 정보가 필요한 경우 인증 창이 나타날 수 있습니다.

CouchDB가 정상적으로 동작하면 다음 단계로 진행합니다.

4. Obsidian에 Self-hosted LiveSync 설치하기

Obsidian을 실행한 뒤 설정으로 이동합니다.

Settings -> Community plugins

아래 순서로 진행합니다.

Restricted mode 끄기
-> Browse 클릭
-> Self-hosted LiveSync 검색
-> Install 클릭
-> Enable 클릭

설치가 끝나면 Obsidian 설정 메뉴에 Self-hosted LiveSync 항목이 추가됩니다.

5. 첫 번째 기기 설정하기

첫 번째 기기는 기준이 되는 Vault로 생각하면 됩니다.

Obsidian에서 다음 메뉴로 이동합니다.

Settings -> Self-hosted LiveSync

설정 방식은 Setup URI 방식이 가장 편하지만, 직접 입력하는 경우 아래 정보를 사용합니다.

Remote Type: CouchDB
Server URI: http://NAS주소:5984
Database Name: obsidiannotes
Username: CouchDB 계정
Password: CouchDB 비밀번호

예시:

Remote Type: CouchDB
Server URI: http://192.168.0.10:5984
Database Name: obsidiannotes
Username: admin
Password: 설정한 비밀번호

입력 후 연결 테스트를 진행합니다.

정상적으로 연결되면 동기화를 활성화합니다.

6. 암호화 설정하기

노트 내용을 보호하고 싶다면 End-to-End Encryption을 켭니다.

암호화에 사용할 비밀번호를 입력합니다.

Encryption Passphrase: 동기화 데이터 암호화용 비밀번호

이 비밀번호는 매우 중요합니다. 다른 기기를 연결할 때도 필요할 수 있으므로 안전한 곳에 보관해야 합니다.

7. 서버 초기 동기화하기

첫 번째 기기 설정이 끝나면 초기 동기화를 실행합니다.

기존 Vault를 서버에 올리는 과정이므로, 진행 전 백업을 권장합니다.

Sync 시작
-> 서버에 Vault 데이터 업로드
-> 완료될 때까지 Obsidian 유지

초기 동기화 중에는 Obsidian을 종료하지 않는 것이 좋습니다.

8. 다른 기기 연결하기

두 번째 기기부터는 첫 번째 기기에서 Setup URI를 만들어 연결하는 방식이 편합니다.

첫 번째 기기에서 명령 팔레트를 엽니다.

Windows:

Ctrl + P

macOS:

Command + P

다음 명령을 실행합니다.

Self-hosted LiveSync: Copy settings as a new Setup URI

생성된 Setup URI를 다른 기기의 Obsidian에 입력합니다.

다른 기기에서는 Self-hosted LiveSync 설치 후 다음 흐름으로 진행합니다.

Welcome to Self-hosted LiveSync
-> I am setting this up for the first time
-> Use a Setup URI
-> Setup URI 붙여넣기
-> 비밀번호 입력
-> 연결 테스트
-> 동기화 시작

9. 동기화 테스트하기

설정이 끝났다면 테스트 노트를 하나 만들어봅니다.

LiveSync 테스트.md

첫 번째 기기에서 내용을 작성한 뒤, 두 번째 기기에서 같은 노트가 나타나는지 확인합니다.

반대로 두 번째 기기에서도 내용을 수정해보고 첫 번째 기기에 반영되는지 확인합니다.

정상적으로 반영된다면 Self-hosted LiveSync 설정이 완료된 것입니다.

주의사항

  • 설정 전 기존 Vault는 반드시 백업하는 것이 좋습니다.
  • iCloud, Dropbox, OneDrive 같은 다른 동기화 서비스와 동시에 사용하지 않는 것이 좋습니다.
  • 외부 접속을 사용할 경우 HTTPS 설정을 권장합니다.
  • CouchDB 계정 비밀번호는 강하게 설정해야 합니다.
  • Setup URI와 암호는 따로 안전하게 보관하는 것이 좋습니다.
  • 여러 기기에서 동시에 같은 파일을 수정하면 충돌이 발생할 수 있습니다.
  • NAS의 oleduc-docker-obsidian-livesync-couchdb-container 컨테이너가 중지되면 동기화가 되지 않습니다.

정리

Self-hosted LiveSync는 설정 난이도가 Remotely Save보다 높습니다.

하지만 NAS에서 CouchDB 컨테이너를 직접 운영하면, 외부 클라우드에 의존하지 않고 Obsidian 동기화 환경을 만들 수 있습니다.

이번 구성에서는 NAS의 Docker 컨테이너인 아래 항목을 CouchDB 서버로 사용합니다.

oleduc-docker-obsidian-livesync-couchdb-container

이 방식은 다음과 같은 사용자에게 잘 맞습니다.

NAS를 가지고 있다
Docker 사용이 가능하다
Obsidian을 여러 기기에서 사용한다
외부 클라우드보다 직접 운영하는 방식을 선호한다
Obsidian Sync 대체 방식을 찾고 있다

결론적으로 Self-hosted LiveSync는 설정은 조금 어렵지만, 구축 후에는 만족도가 높은 자체 동기화 방식입니다.

여러 기기에서 Obsidian을 자주 사용한다면 충분히 선택할 만한 방법입니다.

728x90
728x90

20/30점만 맞추자! 

 

7~11회를 토대로한 3유형 빈출유형

 

 

11회 # 1 오즈비, 비율, 예측값, 민감도 /// 일표본 ttest, 상관분석, 회귀계수

10회 # 1 로지스틱 회귀, pvalue, 오즈비, 예측 문제  /// 회귀계수, r2 , 예측값

9회# 1 설명변수(pvalue), 상관계수, RMSE ///  로지 p value, 오즈비, 예측값

8회 # 1 로지스틱 회귀 pvalue, 로지스틱 회귀 /// 오즈비 2- 설명변수, r2, 예측값

7회 # 1 오즈비, 잔차 이탈도, 오분류표 /// 상관계수, r2, pvalue

 

위주로 나오므로 

# 예측값, 오즈비, Pvalue(설명변수), 상관분석, 잔차이탈도, RMSE, r2 정도만 공부할 예정

 

 

-----

1. 기본적인 모델학습 방법

# 1. X, y 분리
X = df.drop['target'] # df.drop(columns = 'taget') 동일함
y = df['taget']

# 2. 상수항 추가
import statsmodels.api as sm
X_const = sm.add_constant(X)   # statsmodels은 상수항을 넣어줘야함 (y 절편만들어주기)
 

# 3.모델적용 
# a. OLS : 숫자형일때 , Logit : 분류형일때

model = sm.Logit(y, X_const).fit()   
model = sm.OLS(y, X_const).fit()
# y부터 넣어야함!! 2유형이랑 순서다름!!!

# b. GLM 만능이긴한데 r2안나옴(이탈도때 써먹기) #7회 3-2번문제로 나옴
import statsmodels.api as sm # 잔차이탈도 나오면 sm.GLM이랑 Deviance만 기억하면됨!
바로 help(sm.GLM)치면 예시알려줌)
help(sm.GLM)쳐서 24번째줄 따라치면됨 (외우지마셈)

model = sm.GLM(y, X, family=sm.families.Binomial())    # 회귀일때는 family 빼도됨 
result = model.fit()

res_deviance = result.deviance       # 잔차 이탈도 (Residual Deviance)
null_deviance = result.null_deviance # 영 이탈도 (Null Deviance)


학습관련 예시 문제 
유의미한 변수들만 사용하여 로지스틱 회귀 분석을 다시 수행하시오 # 8회 3-1-2
vals = model.pvalues[model.pvalues<0.05].index # 유의미한 변수만 (const 제외)
X_const2 = X_const[vals]
model = sm.Logit(y, X_const2).fit()

 

2. 모델넣고 하는일 [Predict, Pvalues, Params] - #RMSE, 유의미한값, 설명변수, 회귀계수 오즈비

# 모델을 넣고나서 
# 학습한 모델로 .predict를 하던 .pvalues[] 또는 .params를 진행함 

예측을 한다 -> .predict() / 
설명변수, 의미를 찾는다 -> .pvalues[] / 
오즈비, 회귀계수를 찾는다 -> .params[]



---Predict 관련 빈출예시 ---- #예측  #RMSE

# 이탈 확률이 0.3 이상인 고객 수 예측  # 9회 3-2-2
proba = model.predict(X_const)
result = (proba >= 0.3).sum()

# 정해준 값으로 예측
new_data = [[1, 50, 28, 120]] #2차원! 1차원으로 해도상관없긴함 #10회 3-1-2 
pred = model.predict(new_data)
print(pred)

#  RMSE  # 9회 3-1-3
pred = model.predict(X_const)
from sklearn.metrics import root_mean_squared_error
rmse = root_mean_squared_error(y, pred)



---Pvalues 관련 빈출예시---  #유의확률, 유의미한값 #설명변수

# 1. 해당 col의 pvalue 값을 구하여라
result = model.pvalues['col']
print(round(result ,4))

# 2. 의미가 없는 설명변수를 개수는
pvalue1 = model.pvalues.drop('const')  # 모델넣을때 상수를 넣었으니 빼야함 #9회 3-1-1 
result = (pvalue1 >= 0.05).sum()

# 3. 유의수준 0.05 이하인 변수명 추출 # 10회 3-2-2
names = model.pvalues[model.pvalues <= 0.05].index

# 3-1. 유의미한 변수의 이름을 찾겠다. # 8회 3-1-2
name1 = model.pvalues[model.pvalues < 0.05].index

# 3-2 유의확률이 가장 낮은 변수 이름 확인 # 8회 3-2-1
name = model.pvalues.idxmin()
name = model.pvalues.sort_values().index[0] 동일함 


---- Params ----   #회귀계수 #오즈비
# 유의한 회귀계수 확인 # 8회 3-1-2
coef = model.params[model.pvalues < 0.05]
odds = np.exp(coef) # 오즈비 문제 

# 유의한 회귀계수의 합계 # 8회 3-1-2
result = model.params[model.pvalues < 0.05].sum()

 

 

 

 

3. summary() # r2

# 10회 3-2-1

---- 모든 회귀계수의 합-----
# 모든 독립변수를 포함한 회귀모형을 적합하시오. 이때 절편을 제외한 회귀계수의 합을 구하시오.
# heattng_load : 난방 부하 (종속변수) 


# X, y 분리
y = df['heating_load']
X = df.drop(['heating_load'], axis=1)

# 상수항 추가
import statsmodels.api as sm
X_const = sm.add_constant(X)

model = sm.OLS(y, X_const).fit()
summary = model.summary()
print(summary)

model.params[1:].sum() 해도되긴함   # (1은 상수항 제거)

# 사진 1번의 const (절편)을 제외한 나머지값을 더하면 됨


-------r2--------
result = model.rsquared 해도되고     # 10회 3-2-2
summary() 로도 나옴! 값은 똑같음! (사진의 3번 참고)


model = sm.OLS(y, X_const).fit()

result = model.rsquared
summary = model.summary()

print(round(result, 3)) 
print(summary)

 

 

 

 

4. 임계값, 민감도 + 상관분석

------임계값 및 민감도----

임계값 나오면 np.where 바로 생각하기
np.where(조건, 참일때, 거짓일때) 

예시
y_pred = model.predict(x_train)
y_pred2 = np.where(y_pred > 0.5, 1, 0)  # 예측값이 0.5보다 높으면 1로, 아니면 0으로

from sklearn.metrics import recall_score 
score = recall_score(y_train, y_pred2) # 민감도
print(score)

- 혼동행렬없이 바로 metrics에서 메서드 들고오기

<from sklearn.metrics import recall_score, accuracy_score ... 가능함
# 실제값 = y_train, 예측값 = y_pred
recall_score(실제값, 예측값) # 민감도
recall_score(실제값, 예측값) # 특이도
accuracy_score(실제값, 예측값, pos_label=0) # 정확도
precision_score(실제값, 예측값) # 정밀도
confusion_matrix(y_true, 예측값) # 혼동행렬
root_mean_squared_error(실제값, 예측값) # RMSE
f1_score(실제값, 예측값) # f1 score

# 평가지표사용방법 잊어버렸을 때 시험장 꿀팁!!
from sklearn.metrics import get_scorer_names # 평가지표 사용방법확인 # 대신 이름을 알아야함 
print(get_scorer_names()) -> 내가 써야하는 평가지표 찾기 -> help(f1_score) 


------ 상관분석 --------
상관분석이다? 
df.corr(예측값) 바로 이거 생각하기


model = sm.OLS(y, X_const).fit()

# 학습데이터 예측값 확인
pred = model.predict(X_const)

# 학습데이터의 실제값과 예측값의 피어슨 상관계수 확인  #9회 3-1-2   / # 11회 3-1-2
pred.corr(y)                         # 피어슨 상관계수
pred.corr(y, method = 'spearman')    # 스피어만 상관계수


---------------

chi2_contingency() – 범주형 변수의 독립성 검정 (교차표 기반)

두 범주형 변수 간에 통계적으로 연관이 있는지를 검정
from scipy.stats import chi2_contingency
# 예: 교차표 (관찰도수)
table = [[30, 10], [20, 40]]
chi2, p, dof, expected = chi2_contingency(table)


from scipy.stats import chisquare
# 관찰값과 기대값
obs = [30, 50, 20]
exp = [33.3, 33.3, 33.3]  # 예: 균등 분포
chi2, p = chisquare(f_obs=obs, f_exp=exp)

 

 

 

 

 

-------실제 기출문제 ------

 

# 11회 3유형 
# 오즈비, 예측, 민감도 /// 일표본 ttest, 상관분석, 회귀계수


# 다음은 보건소,검진 대상자의 당뇨병 유무를 분석하기 위한 데이터셋이다.
# diabetes(당뇨여부)에 대해 로지스틱 회귀분석을 진행하고자 한다.
# 각 소문항에 대해 답을 구하시오
# (단, diabetes 1= 당뇨, 0= 정상임을 나타낸다)
# 당뇨병 유무(diabetes)를 종속변수로 하고, 나머지를 독립변수로
# 하는 로지스틱 회귀모형을 만들고 아래 문제에 대해 답하시오.
# (단, 모든 답은 반올림하여 소수점 둘째자리까지 구하시오)
# 1-1) age 변수의 오즈비를 구하시오
# 1-2) age=50, bmi=28, blood_sugar=120일 때 당뇨병 유무 확률을 구하시오
# 1-3) 임계값이 0.5일 때 민감도를 구하시오.


import pandas as pd
import numpy as np

X = df.drop(["diabetes"], axis = 1)
y = df["diabetes"]

import statsmodels.api as sm

X_const = sm.add_constant(X)
model = sm.Logit(y, X_const).fit()
# print(model.summary())
# 1-1 age 변수의 오즈비를 구하시오 

odds = np.exp(model.params["age"])



# 1-2 
new_data = [1, 50, 28, 120]
pred = model.predict(new_data)
print(pred)

# 1-3 임계값이 0.5일 때 민감도를 구하시오.

y_pred = model.predict(X_const)
y_pred
y_pred = np.where(y_pred > 0.5, 1,0)

from sklearn.metrics import recall_score
score = recall_score(y, y_pred)
print(score)


# 3유형 2번문제
# 다음은 웹페이지 지표와 홍보비용에 대한 데이터셋이다.
# 아래 소문항에 대해 답하시오.
# (단, 모든 답은 반올림하여 소수점 둘째자리까지 구하시오)
# 2-1) 홍보비용(ad_cost)의 평균이 115,000원이라고 할 수 있는지
# 일표본 t-test 를 진행하여 p-value 값을 구하시오.
# 2-2) 변수들간의 상관분석을 진행하고 가장 큰 상관계수를 구하시오.
# 2-3) ad_cost를 종속변수로 하는 다중회귀모형에서 통계적으로 유의미한 회귀계수의 값을 구하시오.



############# 실기환경 복사 영역 #############
import pandas as pd
import numpy as np
from scipy import stats
import statsmodels.formula.api as smf
np.random.seed(42)
n = 100
visit = np.random.randint (10, 100, n)
duration = np.random.uniform (5, 30, n)
noise = np.random.normal (0, 55000, n)
ad_cost = 2000 + (2075.945 * visit) + (50 * duration) + noise
df = pd. DataFrame({
'visit': visit,
'duration': duration,
'ad_cost': ad_cost
})
                      
############### 실기환경 복사 영역 ############
df.head()

# 1. 일표본 ttest 
statistic, pvalue = stats.ttest_1samp(df['ad_cost'],
                                     popmean =115000,
                                     alternative = 'two-sided') # 같은지 다른지 확인하라했으니 양측
# print(round(statistic,  2), round(pvalue, 2))

#  2. 상관분석 
result = df.corr()
result

# 3.  ad_cost를 종속변수로 하는 다중회귀모형에서
# 통계적으로 유의미한 회귀계수의 값을 구하시오.
# 독립변수와 종속변수 지정
X = df.drop (['ad_cost'], axis=1)
y = df['ad_cost']

# 모델링
import statsmodels.api as sm

X_const = sm.add_constant(X_const)
# 주의: 상수항 추가해줘야 함

model = sm.OLS(y, X_const).fit()
# 주의할 것 : y, x 순으로 입력해야 함

summary = model.summary()

coef = model.params[model.pvalues[model.pvalues < 0.05].index]
print(coef)

print(round(model.params['visit'],2))

 

 

10회 
# 1 로지스틱 회귀 pvalue, 2오즈비, 3예측 문제  / 회귀계수, r2 , 예측 

# 로지스틱 회귀모델을 적용 후 p-value가 0.05보다 작은 변수의 회귀 계수를 구하시오 
# 단 절편항(상수항은 제외한다.
# 반올림하여 소수 셋째 자리까지 작성
# attrition : 이직여부 (0= 잔류, 1=이직) 종속변수
# age (나이) 
# income
# overtime : 초과근무여부
import pandas as pd

# X,y 분리
y = df['attrition']
X = df.drop(['attrition'], axis = 1)

# 상수항
import statsmodels.api as sm
X_const = sm.add_constant(X)

# 로지스틱회귀
model = sm.Logit(y, X_const).fit(disp=0)

# pvalue
model.summary() 
pvalue1 = model.pvalues.drop('const') # 상수항 제거
name = model.pvalues[model.pvalues < 0.05].index # name 인덱스

# 회귀계수

coef1 = model.params['income']
print(round(coef1 ,3))


#3-1-2 나이가 1증가할때 이직할 오즈비를 구하라 (반올림하여 소수3자리

model = sm.Logit(y, X_const).fit()

coef1 = model.params['age']
result = np.exp(coef1)

print(round(result,3))


# 3-1-3 # 새로운 직원 age=40, income=4500, overtime=1 에 대하여, 
# 모델을 이용하여 이직 확률을 예측하시오 (반올림하여 소수 3자리까지)
# new_data = pd.DataFrame([[1, 40, 4500, 1]], columns=X_const.columns) 이게정석이긴함
new_data = pd.DataFrame([[1, 40, 4500, 1]])

result=model.predict(new_data)

print(round(result, 3))


# 10회 3-2-1
# 모든 독립변수를 포함한 회귀모형을 적합하시오. 이때 절편을 제외한 회귀계수의 합을 구하시오. (반올림하여 소수 셋째 자리까지 작성)
# heattng_load : 난방 부하 (종속변수)

import pandas as pd
df=pd.read_csv('data/bigdata_1032.csv')
# X, y 분리
y = df['heating_load']
X = df.drop(['heating_load'], axis=1)

# 상수항 추가
import statsmodels.api as sm
X_const = sm.add_constant(X)

model = sm.OLS(y, X_const).fit()
model.summary()

result = 0.0304 +0.2483+0.2217-0.2469
print(round(result,4))

# 10회 3-2-2
#유의한 변수(유의수준 0.05 이하)만을 사용하여 다중회귀분석을 다시 수행하고, R (결정제수) 을 구하시오.
# (반올림하여 소수 셋째 자리까지 작성)

X_new = X[model.params[model.pvalues < 0.05].index.drop('const')] # X[] 감싸야 이름만 가져오는게 아닌 리스트로 가져옴 []
X_new_const = sm.add_constant(X_new)
x_model = sm.OLS(y, X_new_const).fit() 
r2_score = x_model.rsquared
result = round(r2_score, 3)
print(result)


# 10회 3-2-3 모형을 이용하여 WaLL=20, roof=150, glazing=20, height=5 일 때, heating_load를 예측하시오

new_data = [[1, 150, 20, 5]] # wall 빼고 값넣기
result= x_model.predict(new_data)
print(round(result[0], 3))

 

 

9회
# 1 설명변수(pvalue), 상관계수, RMSE / 2 로지 p value, 오즈비, 예측
# 문제1) 
# 한 제조업체에서는 직원들의 생산성을 향상시키기 위해, 주요 생산성 요인을 분석하고자 하였다. 
# 이를 위해 총 200명의 직원 데이터를 수집하였으며, 각 직원의 근속 기간, 개인 특성 및 속성과 함께 
# 생산성 점수를 기록하였다.

# <data description>
# - id : 데이터의 고유 식별자
# - tenure : 근속 기간
# - f2 ~ f5 : 직원의 개인 특성을 나타내는 변수
# - design : 생산성 점수 (연속형, 예측 대상)

# <데이터 분리조건 >
# - 학습용 데이터 : id가 1 이상 140 이하인 경우
# - 평가용(테스트) 데이터 : id가 141 이상 200 이하인 경우

# =============================================================================
# 1-1) 모든 설명변수(tenure, f2 ~ f5)를 활용하여 design을 예측하는 다중 회귀 분석을 수행하시오.
# 이때 유의하지 않은 설명변수 개수를 구하시오. (패널티는 포함하지 않으며, 모델의 절편항은 포함) 
# =============================================================================
# X, y 분리
y = df1['design']
X = df1.drop(['design', 'id'], axis = 1)

# 상수항 추가
import statsmodels.api as sm
X_const = sm.add_constant(X)

# 회귀모형 적합
model = sm.OLS(y, X_const).fit()

# 유의확률 확인 / 유의하지 않은 설명변수 확인
pvalue1 = model.pvalues.drop('const')
result = (pvalue1 >= 0.05).sum()

# 정답 제출
print(result)


# =============================================================================
# 1-2) 훈련 데이터(학습용 데이터)의 예측값과 실제값의 피어슨 상관계수를 구하시오. 
# 반올림하여 소수점 넷째자리까지 표현
# =============================================================================
# 훈련/테스트 데이터 분리
train = df1[df1['id'] <= 140]
test = df1[df1['id'] > 140]

# X, y 분리
y = train['design']
X = train.drop(['design', 'id'], axis = 1)

# 상수항 추가
X_const = sm.add_constant(X)

# 회귀모형 적합
model = sm.OLS(y, X_const).fit()

# 학습데이터 예측값 확인
pred = model.predict(X_const)

# 학습데이터의 실제값과 예측값의 피어슨 상관계수 확인
pred.corr(y)                         # 피어슨 상관계수
pred.corr(y, method = 'spearman')    # 스피어만 상관계수

# 정답 제출
result = round(pred.corr(y),4)
print(result)


# =============================================================================
# 1-3) 적합한 모델을 활용하여 테스트 데이터에서의 RMSE를 구하시오. 
# 반올림하여 소수점 넷째자리까지 표현
# =============================================================================
# 테스트 데이터 X, y 분리
y = test['design']
X = test.drop(['design', 'id'], axis=1)

# 테스트 데이터 상수항 추가
X_const = sm.add_constant(X)

# 기존 모델사용 -> 예측값 확인
pred = model.predict(X_const)

# RMSE 
from sklearn.metrics import root_mean_squared_error
rmse = root_mean_squared_error(y, pred)

# 정답 제출
result = round(rmse, 4)
print(result)



# =============================================================================
# 9회 문제2) 
# 통신 회사는 고객 이탈을 줄이기 위해 주요 요인을 분석하고자 하였다. 이를 위해 500명의 고객 데이터를 수집하였다. 
# 고객의 서비스 이용 내역과 개인 정보를 기반으로 다음 분석을 수행하시오.
# 
# <data description >
# - col1 : 고객의 첫번째 특성 
# - col2 : 고객의 두번째 특성 
# - Phone_Service : 폰 서비스 가입 여부 
# - Tech_Insurance : 기술 보험 가입 여부 
# - churn : 이탈 여부(1:이탈, 0:유지) 
# =============================================================================
# 2-1) 고객 이탈을 예측하는 로지스틱회귀를 시행한 후 col1 컬럼의 p-value를 구하시오. 
# 반올림하여 소수점 넷째자리까지 표현
# =============================================================================
# X, y 분리
X = df1.drop(columns = 'churn')
y = df1['churn']

# 상수항 추가
import statsmodels.api as sm
X_const = sm.add_constant(X)

# 로지스틱 회귀 모형 적합
model = sm.Logit(y, X_const).fit(disp=0)

# pvalue 확인
result = model.pvalues['col1']

# 정답 제출
print(round(result,4))


# =============================================================================
# 2-2) 폰 서비스를 받지 않은 고객 대비 받은 고객의 이탈 확률 오즈비를 구하시오. 
# 반올림하여 소수점 셋째자리까지 표현
# =============================================================================
# Phone_Service의 회귀 계수
coef1 = model.params['Phone_Service']

# 오즈비 확인
import numpy as np
result = round(np.exp(coef1), 3)

# 정답 제출
print(result)

# =============================================================================
# 2-3) 이탈할 확률이 0.3 이상인 고객 수를 구하시오. 
# =============================================================================
# 이탈 확률
proba = model.predict(X_const)

# 이탈 확률이 0.3 이상인 고객 수
result = (proba >= 0.3).sum()

# 정답 제출
print(result)

 

8회 
# 1 로지스틱 회귀 pvalue, 로지스틱 회귀, 오즈비 2- 설명변수, R 결정계수, 예측
# =============================================================================
# 1-1) 주어진 데이터에서 로지스틱 회귀 분석을 수행하고, 
# 유의확률(p-value)이 0.05 이상인 유의하지 않은 독립변수의 개수를 구하시오.
# (종속변수: Churn, 독립변수: Churn을 제외한 모든 변수)
# =============================================================================
# X, y 분리
y = df1['Churn']
X = df1.drop(columns = 'Churn')

# 로지스틱 회귀 수행
import statsmodels.api as sm
X_const = sm.add_constant(X)              # 상수항 추가
model = sm.Logit(y, X_const).fit(disp=0)

# pvalue 결과 확인
pvalue1 = model.pvalues.drop('const')

# 0.05 이상인 유의하지 않은 독립변수의 개수
result = (pvalue1 >= 0.05).sum()

# 정답 제출
print(result)

# =============================================================================
# 1-2) 1-1에서 구한 결과를 바탕으로, 유의확률이 0.05 미만인 유의한 변수들만 사용하여 
# 로지스틱 회귀 분석을 다시 수행하시오. 이때 유의한 회귀 계수(상수항 포함)의 합계를 구하되, 
# 결과는 반올림하여 소수점 셋째 자리까지 구하시오.
# =============================================================================
# 유의한 변수 확인(상수항 포함)
name1 = model.pvalues[model.pvalues < 0.05].index

# 유의한 변수만 모델링
X_const2 = X_const[name1]
model2 = sm.Logit(y, X_const2).fit(disp=0)

# 유의한 회귀계수 확인
model2.params[model2.pvalues < 0.05]

# 유의한 회귀계수의 합계
result = round(model2.params[model2.pvalues < 0.05].sum(),3)

# 정답 제출
print(result)

# =============================================================================
# 1-3) 1-2에서 생성한 회귀식에서 DataUsage 변수가 5만큼 증가할 때의 오즈비(odds ratio)를 구하시오.
# (소수점 셋째 자리까지 반올림하여 제시할 것)
# =============================================================================

# DataUsage 회귀계수 확인
coef1 =  model2.params['DataUsage']

# 5만큼 증가할 때 오즈비
import numpy as np
result = round(np.exp(coef1 * 5), 3)

# 정답 제출
print(result)


# =============================================================================
# 문제2) 주어진 데이터를 이용하여 종속변수 PIQ와 독립변수 Brain, Height, Weight 간의 다중선형회귀분석을 수행하시오.
# =============================================================================
import pandas as pd
df1 = pd.read_csv('ex_8_3_2.csv')

# =============================================================================
# 2-1) 가장 유의미한 변수(유의확률이 가장 낮은 변수)의 회귀계수 값을 소수점 셋째 자리까지 반올림하여 구하시오.
# =============================================================================
# X, y 분리
y = df1['PIQ']
X = df1.drop(columns = 'PIQ')

# 상수항 추가
import statsmodels.api as sm
X_const = sm.add_constant(X)

# 회귀분석 학습
model = sm.OLS(y, X_const).fit()

# 유의확률이 가장 낮은 변수 이름 확인
vname = model.pvalues.idxmin()

# 해당 변수의 회귀계수 확인
result = round(model.params[vname], 3)

# 정답 제출
print(result)


# =============================================================================
# 2-2) 위에서 생성한 회귀 모델의 결정계수(R²)를 소수점 둘째 자리까지 반올림하여 구하시오.
# =============================================================================
dir(model)
result = round(model.rsquared, 2)

# 정답 제출
print(result)

# =============================================================================
# 2-3) 다음과 같은 독립변수 값이 주어졌을 때 PIQ를 예측하시오.
# (Brain = 90, Height = 70, Weight = 150)
# 예측값은 반올림하여 정수로 출력하시오.
# =============================================================================
# 데이터 생성
new_data = pd.DataFrame({'const' : [1], 'Brain' : [90], 'Height' : [70], 'Weight' : [150]})
new_data= [1, 90, 70, 150] # 와 같음 
# 예측값 확인
result = round(model.predict(new_data).iloc[0])

# 결과 제출
print(result)

 

 

 

7회
1 오즈비, 잔차 이탈도, 오분류표 2- 상관계수, r2, pvalue

# =============================================================================
# 작업형 3유형 
# =============================================================================
# 문제1) 
# 어느 회사의 고객 데이터를 바탕으로 제품 구매 여부를 예측하고자 한다.
# 해당 데이터는 총 100개의 샘플로 구성되어 있으며, 각 샘플에는 다음과 같은 정보가 포함되어 있다:

# - age (나이)
# - income (소득)
# - family_size (가족 수)
# - buy (제품 구매 여부: 0 또는 1)

# 학습용 데이터를 이용하여 로지스틱 회귀 모델을 구축하고, 아래 질문에 답하시오.
# (모형 예측의 임계값은 0.5로 간주한다.)

import pandas as pd
train = pd.read_csv('ex_7_3_1_train.csv')
test = pd.read_csv('ex_7_3_1_test.csv')

# =============================================================================
# 1-1)
# 로지스틱 회귀 모델에서 소득(income) 변수의 오즈비(odds ratio)를 구하시오.
# 반올림하여 소수점 첫째자리까지 표현
# =============================================================================
# 회귀계수 -> exp 함수값 리턴

# X, y 분리
train_x = train.drop('buy', axis=1)
train_y = train['buy']
test_x = test.drop('buy', axis=1)
test_y = test['buy']


# 방법1) sklearn 모델 적용
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()                          # 기본적으로 l2 규제를 사용하므로 statsmodels 함수들과 결과가 달라짐
model = LogisticRegression(penalty=None)              # penalty를 사용하지 않으면 statsmodels 함수들과 결과가 같아짐
 
model.fit(train_x, train_y)

coef1 = model.coef_[0,1]                              # income 변수의 회귀 계수 확인
model.intercept_                                       # 절편

import numpy as np
result = np.exp(coef1)
print(round(result, 1))

# 방법2) statsmodels 라이브러리의 Logit 함수 적용
import statsmodels.api as sm
train_x_const = sm.add_constant(train_x)                # 상수항 추가
model = sm.Logit(train_y, train_x_const).fit()          # disp=0 옵션 사용 시 모델 학습 결과가 출력되지 X
coef1 = model.params['income']

import numpy as np
result = np.exp(coef1)
print(round(result, 1))

# 방법3) statsmodels 라이브러리의 GLM 함수 적용
import statsmodels.api as sm
# train_x_const = sm.add_constant(train_x)                # 상수항 추가

model = sm.GLM(train_y, train_x_const, family=sm.families.Binomial()).fit()
coef1 = model.params['income']

import numpy as np
result = np.exp(coef1)
print(round(result, 1))




# =============================================================================
# 1-2)
# 학습 데이터(train)를 기준으로 잔차 이탈도(Residual Deviance)를 반올림하여 소수점 넷째 자리까지 구하시오.
# =============================================================================
# 잔차제곱합 : 모델이 얼마나 데이터를 잘 설명했는지를 측정(작을수록 잘 설명했다고 볼 수 있음)
# 잔차 이탈도 : 주로 로지스틱 회귀, 포아송 회귀 처럼 비선형 회귀에서 잔차제곱합을 대신하여 모형을 평가하는 척도

import statsmodels.api as sm
# train_x_const = sm.add_constant(train_x)                # 상수항 추가

model = sm.GLM(train_y, train_x_const, family=sm.families.Binomial()).fit()
print(model.summary())

result = model.deviance
print(round(result, 4))

# =============================================================================
# 1-3)
# 테스트 데이터(test)를 이용하여 오분류율(misclassification rate)을 구하시오.
# =============================================================================

statsmodels Logit
import statsmodels.api as sm
# train_x_const = sm.add_constant(train_x)                # train data 상수항 추가
test_x_const = sm.add_constant(test_x)                    # test data 상수항 추가
model = sm.Logit(train_y, train_x_const).fit()
proba = model.predict(test_x_const)                       #  P(Y=1)
pred = np.where(proba >= 0.5,1,0)
(pred != test_y).mean() 

# =============================================================================
# 문제2)
# 다음은 한 기업의 시스템 성능 데이터이다. 아래 지시에 따라 데이터를 분석하고 결과를 도출하시오.
# =============================================================================


# =============================================================================
# 2-1)
# 변수 ERP와 가장 높은 상관관계를 가지는 변수를 찾고, 해당 상관계수 값을 소수점 
# 셋째 자리까지 반올림하여 구하시오.
# =============================================================================
# 상관계수 확인
df_corr = df.corr()         # numeric_only = True 옵션을 사용하면 문자컬럼을 제외하고 숫자컬럼들에 대해서만 상관계수 구함

# ERP와의 상관계수 확인
corr_erp = df_corr['ERP'].drop('ERP')

# 최대 상관계수 확인
result = corr_erp.abs().max()

# 최종 출력
print(round(result, 3))

# =============================================================================
# 2-2)
# 변수 CPU의 값이 100 미만인 데이터만 필터링한 후, ERP를 종속변수로, 나머지 수치형 변수들을 
# 독립변수로 하여 선형 회귀 모델을 적합하고, 그 회귀모형의 결정계수(R²) 값을 소수점 셋째 
# 자리까지 반올림하여 구하시오.
# =============================================================================
# 조건에 맞는 데이터 선택
df2 = df.loc[df['CPU'] < 100]

# X,y 분리
y = df2['ERP']
X = df2.drop(['ERP'], axis=1)

# 방법1) sklearn
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X,y)
result = model.score(X,y)
print(round(result, 3))

# 방법2) statsmodels
import statsmodels.api as sm
X_const = sm.add_constant(X)           # 상수항 추가
model = sm.OLS(y, X_const).fit()       # 모델 적합
model.summary()

print(dir(model))                      # 모델에 대한 정보 확인할 수 있는 메서드 목록
result = model.rsquared                # 결정계수
model.rsquared_adj                     # 수정결정계수 

print(round(result, 3))


# =============================================================================
# 2-3)
# 2-2에서 학습한 회귀모형의 독립변수 중 p-value가 가장 큰 값을 소수점 셋째 자리까지 반올림하여 구하시오.
# =============================================================================
import statsmodels.api as sm
# X_const = sm.add_constant(X)           # 상수항 추가
# model = sm.OLS(y, X_const).fit()       # 모델 적합

# pvalue 확인
pvalue1 = model.pvalues

# 독립변수 중(const제외) pvalue 최대값 확인
result = pvalue1.drop('const').max()

# 결과 제출
print(round(result, 3))
728x90
728x90

100점을 위한 공부가 아닌 시험합격을 위한 공부!

나의 목표는 70점을 목표로 합격하는 것!

 

1유형 20/30점 (기본기에 충실!)

2유형 30/40점 (랜포+XGB 만 잘 써먹자!)

3유형 20/30점 (빈출유형 10개만 공부하기!)

 

버릴껀 빠르게 버리고 시험에 계속나오는 건 무조건 맞추자!!

암기위주로 한다면 3일도 가능

 

1유형은  (1일 공부)

https://itcreator.tistory.com/328

 

빅분기 1유형 총 정리

# 판다스 기본 인덱스# ---- 기본인덱싱 ----df.index[1] # df 1번 인덱스 df.iloc[1] # df 1행df.iloc[1][0] df # 1행 0열df.loc[1,"컬럼명"] # 1행 / 열이름이 "컬럼명"인 값을 추출 df['컬럼명'].iloc[0] # 해당 컬럼의 0번

itcreator.tistory.com

 

2유형은 (2일)

https://itcreator.tistory.com/323

 

빅분기 2유형 탬플릿 30/40 버전 (26년 이후용)

랜포 모델 하나만 생각하고 진행하는 버전 + 하이퍼파라미터는 진행함2시간 암기면 끝나도록 작업함 # 일단 전처리부터 import pandas as pdtrain = pd.read_csv("data/customer_train.csv") # csv 파일이름은 상황에

itcreator.tistory.com

 

 

3유형은 (2일)

https://itcreator.tistory.com/330

 

빅분기 3유형 총 정리 (2일용)

20/30점만 맞추자! 7~11회를 토대로한 3유형 빈출유형 11회 # 1 오즈비, 비율, 예측값, 민감도 /// 일표본 ttest, 상관분석, 회귀계수10회 # 1 로지스틱 회귀 pvalue, 2오즈비, 3예측 문제 /// 회귀계수, r2 , 예

itcreator.tistory.com

 

최종점검(1일)

728x90
728x90

이것만 공부해도 20/30 점 가능

# 판다스 기본 인덱스

# ---- 기본인덱싱 ----
df.index[1] # df 1번 인덱스 
df.iloc[1] # df 1행
df.iloc[1,0]  # 1행 0열   #iloc 순서 / loc 이름
df.loc[1,"컬럼명"] # 인덱스 이름이 1인 / 열이름이 "컬럼명"인 값을 추출 

df['컬럼명'].iloc[0] # 해당 컬럼의 0번째 행 

# 1. 행은 전체(:), 열은 특정 컬럼 이름으로 여러 개 추출할 때
df.loc[:, ['성별', '나이', '지역']]  # 은 전체(:), 열은 특정 컬럼 이름으로 여러 개 추출할 때

# 2. loc으로 슬라이싱할 때는 마지막 값도 포함됩니다! (iloc과의 가장 큰 차이)
df.loc[:, '성별':'지역'] # 성별 컬럼부터 지역 컬럼까지 싹 다 추출

# ---- 2중 df ---- 

new_data = df[df['name'] == 'A'] # A만 따로 data모음
A_boolean = df['name'] == 'A' # A인지 아닌지 True/False 판단을함

# ---- 정렬 ---- 
.sort_values(ascending=False) # 내림차순 정렬, 높은값 -> 낮은값
df['연봉'].sort_values(ascending=False) # 연봉 내림차순정렬
# ---- 조건 ----
# 1. 단일 조건
df[df['나이'] >= 30] # 나이가 30 이상인 행만 추출

# 2. 다중 조건
# 주의: 조건마다 반드시 소괄호()를 씌워야 에러가 안 납니다.
df[(df['나이'] >= 30) & (df['성별'] == '남')] 

# 3. where 조건
np.where(조건, 참일때, 거짓일때)
df['합격여부'] = np.where(df['점수'] >= 80,"합격", "불합격")
df['매출보정']= np.where(df['반품여부']=1, -df["매출"], df["매출"]  # 반품이 된거라면 매출보정란에 매출값에 - 붙이기

 

# 글자 인덱싱 

# ------ .str[:] ------

# 예시 데이터: df['주민번호'] = '901225-1234567'

# 1. 앞에서부터 6글자만 자르기 (생년월일)
df['생년월일'] = df['주민번호'].str[0:6]  # 또는 .str[:6]

# 2. 특정 위치의 1글자만 가져오기 (성별 코드, 인덱스 7번)
df['성별코드'] = df['주민번호'].str[7]

# 3. 뒤에서부터 7글자만 가져오기
df['뒷자리'] = df['주민번호'].str[-7:]


# ----- .str.len()
# 예시 데이터: df['과일'] = ['사과', '바나나', ' 빅분기 '] 
df['글자수'] = df['과일'].str.len()

# 결과:
# '사과' -> 2
# '바나나' -> 3
# ' 빅분기 ' -> 5 (앞뒤 띄어쓰기 포함)


#----- .str.split('')------

# 예시 데이터: df['주소'] = '서울특별시 강남구 테헤란로'

# 1. 띄어쓰기를 기준으로 리스트로 쪼개기
# 결과: ['서울특별시', '강남구', '테헤란로']
df['주소'].str.split(' ')

# 꿀팁: expand=True 를 쓰면 쪼개진 글자들이 아예 새로운 컬럼들로 분리됩니다!
df[['시도', '구', '도로명']] = df['주소'].str.split(' ', expand=True)


# ------ .str.contains('') -----
Python
# '서울'이 포함된 행만 True로 반환
cond = df['주소'].str.contains('서울')  ('Seoul', case=False) # case = False  대소구분 x
# '서울' 사는 사람만 추출!
seoul_df = df[cond] #seoul_df[df['주소'].str.contains('서울')] 와 동일한 원리

tip! .astype(str) 을 쓰는게 좋음 나중에 해당컬럼의 값이 숫자인지 판단안될때 오류방지 예시 
cond = df['전화번호'].astype(str).str.contains('01012341234') # 시험칠때는 몰라도 크게 상관엄



# ----- .str.replace('' ,'')
# 예시 데이터: df['가격'] = '1,000원'

# 1. '원' 글자를 빈 문자열('')로 바꿔서 지우기
df['가격'] = df['가격'].str.replace('원', '')

# 2. 쉼표(,) 지우기
df['가격'] = df['가격'].str.replace(',', '')

# (참고) 글자를 다 지웠으면 숫자로 바꿔줘야 계산이 가능합니다!
df['가격'] = df['가격'].astype(int)

 

#Groupby + unstack 

# 1. 단일 그룹화   #해당 지역의 총매출을 구하시오
df.groupby("지역")["매출"].sum()

# 2. 다중 그룹화 (지역별, 그리고 그 안에서 상품별 매출 합계)
multi_group = df.groupby(["지역", "상품"])["매출"].sum()

# 3. reset_index()
# groupby를 하면 '지역'과 '성별'이 인덱스가 되어버림 (행 수가 달라짐)
grouped = df.groupby(['지역', '성별'])['매출'].mean() 

# 인덱스되는게 싫으면 transformed를 쓰면됨 (행 수 동일)
transformed = df.groupby(['지역', '성별'])['매출'].transform('mean')

# ⭐️ 치트키 발동: 인덱스로 올라간 애들을 다시 평범한 컬럼으로 끌어내림!
# 여기서는 예전 인덱스(지역, 성별)를 컬럼으로 살려야 하니까 drop=True를 쓰지 않습니다.
final_df = grouped.reset_index()

 

 

 

# 시간 

df.info() 를 진행했을때 타입이 object라면 datetime으로 타입변환 진행 
order_date = "2023-10-25 15:30:02" 인 경우
df['date_col']=pd.to_datetime(df['order_date'])


# ------- 원하는 날만 추출하기------
# ---dt. ---
df['year'] = df['date_col'].dt.year 
df['hour'] = df['date_col'].dt.hour

df['date_col'].dt.year				연도 숫자만 추출	2023
df['date_col'].dt.month				월 숫자만 추출	10
df['date_col'].dt.day				일 숫자만 추출	25
df['date_col'].dt.hour				시 숫자만 추출	15
df['date_col'].dt.minute			분 숫자만 추출	30
df['date_col'].dt.second			초 숫자만 추출	02



# --- dt.to_period('') ----
df['date_col'].dt.to_period('Y')	연 단위 기간으로 묶기	2023
df['date_col'].dt.to_period('Q')	분기 단위 기간으로 묶기	2023Q4
df['date_col'].dt.to_period('M')	월 단위 기간으로 묶기	2023-10
df['date_col'].dt.to_period('D')	일 단위 기간으로 묶기	2023-10-25
df['date_col'].dt.to_period('H')	시간 단위		2023-10-25 15:00



# 1. 요일을 숫자로 추출 (dt.dayofweek):
월요일(0) 부터 일요일(6) 까지 숫자로 반환합니다.
df['day_of_week'] = df['date_col'].dt.dayofweek

# 2. 주말만 골라내기 (응용):
토(5), 일(6) 이므로 숫자가 5 이상인지 확인하면 끝입니다.
df['is_weekend'] = df['date_col'].dt.dayofweek >= 5 (결과: True/False)

# 3. 요일을 영어 이름으로 추출 (dt.day_name()):
df['day_name'] = df['date_col'].dt.day_name() (결과: 'Monday', 'Tuesday' ...)



# 1. 두 날짜의 차이 계산
df['time_diff'] = df['종료일'] - df['시작일']

# 2. '며칠' 차이인지 숫자(int)만 추출
df['diff_days'] = df['time_diff'].dt.days

# 3. '몇 초' 차이인지 숫자(int)만 추출
df['diff_seconds'] = df['time_diff'].dt.seconds

 

 

# 통계량 

----- 기본 통계량 -----

.mean() : 평균
.median() : 중앙값 (데이터를 크기순으로 세웠을 때 정중앙에 있는 값)
.max() : 최댓값
.min() : 최솟값
.mode()[0] : 최빈값 (가장 자주 등장한 값. 결과가 리스트로 나오므로 꼭 [0]을 붙여서 첫 번째 값을 꺼내야 함!)

# 기본 통계량 실전 예시
mean_val = df['매출'].mean()      # 매출 컬럼의 평균
mode_val = df['카테고리'].mode()[0] # 카테고리 컬럼의 최빈값 (가장 많이 팔린 것)


----- 퍼진 정도를 나타내는 통계량 -----

.std() : 표준편차 (Standard Deviation)
.var() : 분산 (Variance)

# 예시
std_val = df['온도'].std()  # 온도의 표준편차 구하기
var_val = df['온도'].var()  # 온도의 분산 구하기

-----  데이터의 모양을 나타내는 통계량 -----

.skew() : 왜도 (비대칭도). 양수면 왼쪽으로 치우침, 음수면 오른쪽으로 치우침.
.kurt() : 첨도 (뾰족한 정도). 클수록 중심에 데이터가 뾰족하게 몰려있음.

#예시
skew_val = df['가격'].skew()
print(skew_val)

----- 스케일러 -----

from sklearn.preprocessing import MinMaxScaler, StandardScaler, RobustScaler
#scaler = MinMaxScaler()
#scaler = StandardScaler()
#scaler = RobustScaler()

cols = ['CO(GT)', 'NMHC(GT)']
df[cols] = scaler.fit_transform(df[cols])


----- 분위수와 이상치 -----

.quantile(0.25) : 1사분위수 (Q1, 하위 25% 지점의 값)
.quantile(0.75) : 3사분위수 (Q3, 상위 25% 지점의 값)

IQR (사분위범위) : Q3 - Q1 (이 값을 이용해 이상치를 판별하는 문제가 아주 자주 나옵니다!)

이상치 하한선: Q1 - 1.5 * IQR 보다 작은 값
이상치 상한선: Q3 + 1.5 * IQR 보다 큰 값

# 예시
Q1 = df['매출'].quantile(0.25)
Q3 = df['매출'].quantile(0.75)
IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR # 이상치 하한선
upper_bound = Q3 + 1.5 * IQR # 이상치 상한선

# 하한선보다 작거나(|) 상한선보다 큰(>) 데이터만 필터링
outliers = df[(df['매출'] < lower_bound) | (df['매출'] > upper_bound)]

print(len(outliers)) # 이상치의 총 갯수 출력

 

# 심화 (멀티인덱스 + 셋인덱스 +  피벗 + ??)  시간남으면 공부 

피벗 long -> wide

# df_wide = df.pivot(
#     index="country",
#     columns="year",
#     values="emissions"
# ).reset_index()

# df_wide.columns.name = None

# print(df_wide.head(3))

멜트 wide -> long 
df_long = pd.melt(
    df,
    id_vars="country",
    var_name="year",
    value_name="emissions"
)

 

-----------------------

 

 

# 인덱싱관련 문제

# 11회 1번문제
# 다음은 연도별(2001~2021) 온실가스 배출 데이터이다.
# 연도별 배출량 1위를 가장 많이 한 국가의 1위 횟수를 구하시오.


count = df.loc[:,'2001':'2021'].idxmax()  # 2001, 2021 문자열로 판단

result = count.value_counts().sort_values(ascending=False)
a = result.iloc[0]
print(a)


# 11회 3번문제 
3-1번
# 다음은 고객별 거래코드 및 매출액 데이터이다.
# 거래코드가 C로 시작하면 주문취소 코드라고 할 때
# 주문취소 금액(매출액)이 가장 큰 고객의 고객코드를 구하시오.
df["매출액"] = df["Quantity"] * df["Unit_price"]
df2 = df[df["transaction_code"].str.astype(str).str.startswith("C")]
df3 = df2.groupby('customer_id')['매출액'].sum().sort_values(ascending=False)
a= df3.index[0]

3-2번
# 주문취소 금액은 음수로 처리하고, 매출액이 가장 큰 고객의 매출액을 구하시오.

df["매출보정"] = np.where(df['transaction_code'].astype(str).str.startswith('C'), -df["매출액"] , df["매출액"])
result = df.groupby("customer_id")["매출보정"].sum().sort_values(ascending=False)
result.index[0]

 

 

# 글자인덱싱 문제 

# 10회 문제 3¶
# 제공된 데이터(hamspam.csv)는 문자 메시지 내용과 스팸 여부를 담고 있다. 
아래 수행 순서에 따라 데이터를 처리한 뒤, 구한 값을 [제출 형식]에 맞춰 답안 페이지에 입력하시오.

# 제공 데이터

# label : 메시지 구분 (spam: 스팸, ham: 정상)
# text : 메시지

# 각 메시지의 단어 개수를 띄어쓰기(공백) 기준으로 계산하시오.
# 스팸 메시지의 평균 단어 개수와 정상 메시지의 평균 단어 개수를 각각 구하시오.
# 두 평균의 차이의 절댓값을 구하여 입력하시오.

df["단어"] = df["text"].str.split()
df["단어수"] = df["단어"].str.len()
df.head()

# 2. 스팸과 정상 메시지의 평균 단어 수 구하기
m = df.groupby("label")["단어수"].mean()

# 3. 두 평균 차이의 절댓값 구하기
diff = abs(m["spam"] - m["ham"])
print(m.["spam"], m.["ham"])

 

 

# Goupby + unstack 관련 문제

# 문제1)
# 1) 총대출액은 신용대출과 담보대출의 합으로 정의한다.
# 2) 각 지역코드 내에서 성별별(1과 2)로 총대출액의 합계를 계산하시오.
# 3) 이후, 성별 간 총대출액의 차이가 가장 큰 지역코드를 구하시오. (단, 차이는 절대값 기준)
# =============================================================================


df1['총대출액'] = df1['신용대출'] + df1['담보대출']

df_mean = df1.groupby(["지역코드", "성별"])["총대출액"].sum()
df2 = df_mean.unstack()

diff = (df2[1] - df2[2]).abs().sort_values(ascending=False)
result = diff.index[0] #  diff.idxmax() 랑 같음
# print(result)

 

unstack 진행 완료
초기 > 그룹바이 > 언스택 순서

 

 

# 시간관련 문제 

# 10회 문제2¶
# 제공된 데이터(cafe_sales.csv)는 2024년 4월부터 2025년 12월까지의 카페 메뉴 판매 이력이다. 소문항을 각각 구한 다음 [제출 형식]에 맞춰 답안 페이지에 입력하시오.

# 제공 데이터

# order_date : 주문 날짜 (예 2024.05.24 13:22)
# category : 음료/디저트 종류 (예 coffee, tea …)
# item : 메뉴명
# price : 판매 금액
# 소문항

# 2-1. 연-월별 총 매출액을 계산하여 큰 순서대로 정렬했을 때, 2번째로 큰 매출액을 입력하시오.
# 2-2. 연-월별 총 매출액이 4번째로 큰 연-월을 찾으시오. 해당 연-월의 데이터에서 카테고리별 매출 합계를 계산하고, 그중 최댓값을 입력하시오.

df['order_date']=pd.to_datetime(df['order_date']) # object 타입이라 datetime 으로 변경 
df["year_month"] = df["order_date"].dt.to_period("M") # 2024-10 형태의 년-월 형태로 변경 
month_sales = df.groupby("year_month")["price"].sum().sort_values(ascending=False)  # 기간별 매출합계

target_month = month_sales.index[3] # 기간별 매출합계가 4번째인 년-월 

# # 2. 4번째로 큰 연-월에 해당하는 데이터만 추출
cond = df["year_month"] == target_month
df = df[cond]  # 해당 년-월 자료만 표시 
cate_sales = df.groupby("category")["price"].sum().sort_values(ascending=False) # 카테고리별 매출로 표시

result = cate_sales.iloc[0]
print(result)

 

 

# 통계량 관련문제

# =============================================================================
# 8회 3번 문제 
# CO(GT)와 NMHC(GT) 두 컬럼에 대해 Min-Max 스케일링을 수행한 후, 
# 스케일링된 CO(GT)의 표준편차를 a (소수점 셋째 자리에서 반올림),
# 스케일링된 NMHC(GT)의 표준편차를 b (소수점 셋째 자리에서 반올림)라 할 때,
# a + b 값을 구하시오.
# =============================================================================

import pandas as pd
from sklearn.preprocessing import MinMaxScaler

# 1. 스케일러 소환
scaler = MinMaxScaler()

# 2. 두 컬럼을 한 번에 스케일링해서 덮어씌우기 (반드시 괄호 두 개 [[ ]] 사용!)
cols = ['CO(GT)', 'NMHC(GT)']
df[cols] = scaler.fit_transform(df[cols])

# 3. 표준편차 구하고 반올림하기 (소수점 셋째 자리에서 반올림 = 둘째 자리까지 남김)
a = round(df['CO(GT)'].std(), 2)
b = round(df['NMHC(GT)'].std(), 2)

# 4. 정답 출력
print(a + b)
728x90

728x90

1시간 암기용

 

 

 

# 데이터 확인 

print(train.head(3))
print(train.isnull().sum())

# 결측치가 있는경우!!! 결측치 처리방법 
# 2. 데이터 전처리 - train, test 둘 다 처리! (→ But, 보통 결측치 없는 데이터로 출제됨) 
train['A'] = train['A'].fillna(train['A'].mean()) # 평균 대체
test['A'] = test['A'].fillna(test['A'].mean())
train['A'] = train['A'].fillna(train['A'].mode()[0]) # 최빈값 대체
train['A'] = train['A'].fillna(0) # 0으로 대체
train['A'] = train['A'].fillna(method='bfill') # 뒤 값으로 대체
train = train.dropna() # 전체 결측치 데이터 삭제
train = train.dropna(subset=['A', 'B']) # 특정컬럼의 결측치 데이터 삭제
train = train.dropna(axis=1) # 결측치 있는 컬럼 삭제
print(train["종속변수"].value_counts()) # 불균형데이터인지 확인

# X, y 분리 
X = train.drop(["변수"], axis=1)
y = train["변수"]

# 원핫인코딩 
X_full = pd.concat([X, test], axis=0)
X_full = pd.get_dummies(X_full)

X_train= X_full[:train.shape[0]]
X_test=X_full[train.shape[0]:]

# 학습용, 검증 데이터 분리
from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y, random_state=42)

# 모델 학습 
from sklearn.ensemble import RandomForestClassifier  # 회귀라면  RandomForestRegressor 로 변경
model = RandomForestClassifier(n_estimators=42, random_state=42)
model.fit(X_tr, y_tr)
model.score(X_val, y_val)

# 전체 학습
model.fit(X_train, y)

pred = model.predict(X_test)

# 결과저장 
result = pd.DataFrame({"pred": pred})
result.to_csv("result.csv", index=False)

# 생성확인
result_check = pd.read_csv("result.csv")
print(result_check)

 

 

 

 

728x90
728x90

랜포 모델 하나만 생각하고 진행하는 버전 

+ 하이퍼파라미터는 진행함

2시간이면 암기가능!! 

 

 

# 일단 전처리부터 

# 1. 데이터 형태 확인방법들  -> 이 단계에서 회귀문제인지 분류 문제인지 판단
print(train.shape)
print(train.head(5))
print(train.describe(include="all"))
print(train.info()) # 범주형 변수 확인
print(test.info())
print(train.isnull().sum()) # 결측치 확인
print(test.isnull().sum())
print(train["종속변수"].value_counts()) # 불균형인지 확인 


# 2. 결측치 처리방법
------ 결측치 전처리는 train, test 둘 다 처리 해야함!!
train['A'] = train['A'].fillna(train['A'].mean()) # 평균 대체
test['A'] = test['A'].fillna(test['A'].mean())  이런식으로!! 밑에는 test는 생략함

train['A'] = train['A'].fillna(train['A'].mode()[0]) # 최빈값 대체
train['A'] = train['A'].fillna(0) # 0으로 대체
train['A'] = train['A'].fillna(method='bfill') # 뒤 값으로 대체
train = train.dropna() # 전체 결측치 데이터 삭제
train = train.dropna(subset=['A', 'B']) # 특정컬럼의 결측치 데이터 삭제
train = train.dropna(axis=1) # 결측치 있는 컬럼 삭제
train.set_index('id') 
test.set_index('id') # train 했으면 test도 반드시 해야함

-----시간관련 데이터가 있는경우----  # 8회 2유형
for df in [train, test]:
	df["date_time"] = pd.to_datetime(df["date_time"])
    #df["hour"] = df["date_time"].dt.hour           # 시간 (0~23)
    #df["day"] = df["date_time"].dt.dayofweek       # 요일 (0~6)
    #df["month"] = df["date_time"].dt.month         # 월 (1~12)
    #df["is_holiday"] = df["date_time"].dt.dayofweek >= 5 # 주말 여부
    df.set_index('date_time', inplace=True)  #     !!!필수!!!
  	

# 3.X,y 세팅 

X = train.drop(['최종확인값'], axis=1) 
y = train['최종확인값'] # 예측 대상


# 4. 원핫 인코딩 준비작업 
# train + test 합치기
X_full = pd.concat([X, test])
X_full = pd.get_dummies(X_full)
X_train = X_full[:train.shape[0]]
X_test = X_full[train.shape[0]:]

# 5. 학습용, 검증 데이터 분리 및 그리드서치 준비
from sklearn.model_selection import train_test_split, GridSearchCV
X_tr, X_val, y_tr, y_val = 
train_test_split(X_train, y, random_state=42) # 분류일때 stratify = y 넣기! (비율에 맞춰 자르기)

 

 

 

#회귀

# 1. 튜닝의 뼈대가 될 기본 모델 생성
# 주의: 회귀 모델은 연속된 숫자를 맞추는 것이라 class_weight="balanced" 옵션이 없습니다!
from sklearn.ensemble import RandomForestRegressor  # Classifier가 아닌 Regressor!
base_model = RandomForestRegressor(random_state=42)
# from lightgbm import LGBMRegressor
# base_model = LGBMRegressor(random_state=42, verbose=-1) # verbose =-1 로그숨김
# from xgboost import XGBRegressor
# base_model = XGBRegressor(random_state=42)


param_grid = {
    'n_estimators': [50, 100, 150],  # 나무의 개수
    'max_depth': [5, 10, 15]       # 나무의 깊이
    # 'learning_rate': [0.01, 0.05, 0.1] # 부스팅모델은 추가가능
}

# 3. GridSearchCV 객체 생성
# cv=3 : 3등분하여 교차 검증 (시간 절약을 위해 3 추천)
grid_search = GridSearchCV(
    estimator=base_model,
    param_grid=param_grid,
    scoring='neg_root_mean_squared_error',  # RMSE로 평가  
	# neg_mean_absolute_error, neg_mean_squared_error, r2 등인데 neg 넣는거 잊지말자!
)

print("하이퍼파라미터 탐색")
# 4. 탐색 시작 (쪼개둔 훈련용 데이터 X_tr, y_tr 사용)
grid_search.fit(X_tr, y_tr)

# 5. 튜닝 결과 확인
print("가장 좋은 파라미터:", grid_search.best_params_)
# grid_search.best_score_ # 점수보기

# 가장 똑똑하게 튜닝된 최종 모델을 변수에 담아줍니다.
#best_model = grid_search.best_estimator_
# 파라미터 찾았으면 위에 전부 주석처리하고 찾은 파라미터값 넣기  
best_model = RandomForestRegressor(max_depth=10, n_estimators=50, random_state=42)
best_model.fit(X_tr, y_tr)

# =============================================================================
# 검증 (튜닝된 최고 모델 사용)
# =============================================================================
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np

# 그냥 model이 아니라 best_model이 문제를 풀게 합니다.
y_pred = best_model.predict(X_val)

print("검증 데이터 평가 결과")
# 회귀는 정확도가 아니라 '오차(Error)'와 '설명력(R2)'을 봅니다.
mse = mean_squared_error(y_val, y_pred)
rmse = np.sqrt(mse) #  = mse ** 0.5 도 가능
r2 = r2_score(y_val, y_pred) # 1에 가까울수록 모델이 예측을 잘한다는 뜻입니다.

print("RMSE (평균 제곱근 오차):", rmse)
print("R2 Score (결정계수):", r2)


# =============================================================================
# 전체 train으로 다시 학습 및 최종 예측
# =============================================================================
# 성능을 영혼까지 끌어모으기 위해, 쪼개기 전의 전체 데이터(X_train, y)로 최종 학습
best_model.fit(X_train, y)

# 진짜 시험지(test) 데이터 예측 (회귀이므로 예측 결과가 연속된 숫자들로 나옵니다)
pred = best_model.predict(X_test)

# 결과 저장
result = pd.DataFrame({
    "pred": pred
})

result.to_csv("result.csv", index=False)

# 생성 결과 확인

result_check = pd.read_csv("result.csv")
print(result_check.head())

 

 

 

 

#분류

# 1. 튜닝의 뼈대가 될 기본 모델 생성
from sklearn.ensemble import RandomForestClassifier
base_model = RandomForestClassifier(random_state=42, class_weight="balanced")
# from lightgbm import LGBMClassifier
# base_model = LGBMClassifier(random_state=42, verbose=-1) # verbose=-1: 로그숨김
# from xgboost import XGBClassifier
# base_model = XGBClassifier(random_state=42)

# 2. 탐색할 파라미터 후보군 설정 
# (시험 환경의 1분 시간 초과 방지를 위해 후보를 너무 많이 넣지 않는 것이 좋습니다!)
param_grid = {
    'n_estimators': [50, 100, 150],  # 나무의 개수
    'max_depth': [5, 10, None]        # 나무의 깊이 (None은 끝까지 자란다는 뜻)
	# 'learning_rate': [0.01, 0.05, 0.1] # 부스팅 모델은 추가가능
}

grid_search = GridSearchCV(
    estimator=base_model,
    param_grid=param_grid,
    scoring='f1_macro', # 평가지표로 매크로 f1
	# accuracy, f1 # 문제에 맞게 넣어주기
)

print("하이퍼파라미터 탐색")
# 4. 탐색 시작 (우리가 쪼개둔 훈련용 데이터 X_tr, y_tr 사용)
grid_search.fit(X_tr, y_tr)

# 5. 튜닝 결과 확인
print("가장 좋은 파라미터:", grid_search.best_params_)
# grid_search.best_score_ # 점수보기

# 가장 똑똑하게 튜닝된 최종 모델을 변수에 담아줍니다.
# best_model = grid_search.best_estimator_
# 파라미터 찾았으면 위에 전부 주석처리하고 찾은 파라미터값 넣기  
best_model = RandomForestClassifier(max_depth=10, n_estimators=50, random_state=42)
best_model.fit(X_tr, y_tr)


# =============================================================================
# 검증 (튜닝된 최고 모델 사용)
# =============================================================================
from sklearn.metrics import accuracy_score, f1_score, classification_report

# 그냥 model이 아니라 best_model이 문제를 풀게 합니다.
y_pred = best_model.predict(X_val)

print("검증 데이터 평가 결과")
print("accuracy:", accuracy_score(y_val, y_pred))
print("macro f1:", f1_score(y_val, y_pred, average="macro"))
print(classification_report(y_val, y_pred))


# =============================================================================
# 전체 train으로 다시 학습 및 최종 예측
# =============================================================================
# 성능을 영혼까지 끌어모으기 위해, 쪼개기 전의 전체 데이터(X_train, y)로 최종 학습
best_model.fit(X_train, y)

# 진짜 시험지(test) 데이터 예측
pred = best_model.predict(X_test)

# 결과 저장
result = pd.DataFrame({
    "pred": pred
})

result.to_csv("result.csv", index=False)

# 생성 결과 확인
result_check = pd.read_csv("result.csv")
print(result_check.head())

 

 

# 파라미터 기억안날때 

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
help(model)
from sklearn.model_selection import GridSearchCV
help(GridSearchCV)

 

728x90
728x90

11회때 불균형 데이터를 참고하여

1. 불균형 데이터 정밀학습 

2. 최선의 모델 찾기

3. 최선의 모델 파리미터 미세조정을 진행하는 2유형 작업탬플릿입니다. 

 

# 전처리

# 1. 데이터 형태 확인방법들  -> 이 단계에서 회귀문제인지 분류 문제인지 판단
print(train.shape)
print(train.head(5))
print(train.describe(include="all"))
print(train.info()) # 범주형 변수 확인
print(test.info())
print(train.isnull().sum()) # 결측치 확인
print(test.isnull().sum())
print(train["종속변수"].value_counts()) # 불균형인지 확인 


# 2. 결측치 처리방법
------ 결측치 전처리는 train, test 둘 다 처리 해야함!!
train['A'] = train['A'].fillna(train['A'].mean()) # 평균 대체
test['A'] = test['A'].fillna(test['A'].mean())  이런식으로!! 밑에는 test는 생략함

train['A'] = train['A'].fillna(train['A'].mode()[0]) # 최빈값 대체
train['A'] = train['A'].fillna(0) # 0으로 대체
train['A'] = train['A'].fillna(method='bfill') # 뒤 값으로 대체
train = train.dropna() # 전체 결측치 데이터 삭제
train = train.dropna(subset=['A', 'B']) # 특정컬럼의 결측치 데이터 삭제
train = train.dropna(axis=1) # 결측치 있는 컬럼 삭제

-----시간관련 데이터가 있는경우----
for df in [train, test]:
	df["date_time"] = pd.to_datetime(df["date_time"])
    #df["hour"] = df["date_time"].dt.hour           # 시간 (0~23)
    #df["day"] = df["date_time"].dt.dayofweek       # 요일 (0~6)
    #df["month"] = df["date_time"].dt.month         # 월 (1~12)
    #df["is_holiday"] = df["date_time"].dt.dayofweek >= 5 # 주말 여부
    df.set_index('date_time', inplace=True)  #     !!!필수!!!
  	

# 3.X,y 세팅 

X = train.drop(['최종확인값'], axis=1) 
y = train['최종확인값'] # 예측 대상


# 4. 원핫 인코딩 준비작업 
# train + test 합치기
X_full = pd.concat([X, test])
X_full = pd.get_dummies(X_full)
X_train = X_full[:train.shape[0]]
X_test = X_full[train.shape[0]:]


# ---라벨인코딩의 경우--- 
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

for col in train.columns :
    if train[col].dtype == 'object' :
        le.fit(pd.concat([train[col], test[col]]))
        train[col] = le.transform(train[col])
        test[col] = le.transform(test[col])

 

 

# 회귀

# 분류(Classifier)가 아닌 회귀(Regressor) 모델을 사용합니다.
# (데이터 불러오기 및 결측치/원핫인코딩 처리 등 전처리가 끝난 상태라고 가정합니다.)


from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(X_train, y, random_state=42) 

# =============================================================================
# 1. 3가지 회귀 모델 성능 비교 (RMSE 기준, 낮을수록 좋음)
# =============================================================================
from sklearn.ensemble import RandomForestRegressor
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from sklearn.metrics import mean_squared_error
import numpy as np



models = {
    "RandomForest": RandomForestRegressor(random_state=42),
    "LightGBM": LGBMRegressor(random_state=42),
    "XGBoost": XGBRegressor(random_state=42)
    
}

best_model_name = ""
# 오차(Error)는 낮을수록 좋으므로, 초기값을 무한대(inf)로 설정합니다.
best_score = float('inf') 

print("기본 모델 성능 비교 (RMSE 오차 점수)")
for name, model in models.items():
    model.fit(X_tr, y_tr)
    pred_val = model.predict(X_val)
    
    # RMSE(Root Mean Squared Error) 계산: mse에 루트(np.sqrt)를 씌움
    mse = mean_squared_error(y_val, pred_val)
    rmse = np.sqrt(mse)
    print(f"{name} 모델 RMSE: {rmse:.4f}")
    
    # 오차가 이전 최저 오차보다 '작다면(낮다면)' 최고 모델 갱신
    if rmse < best_score:
        best_score = rmse
        best_model_name = name

print(f"가장 좋은모델: {best_model_name} (최저 오차: {best_score:.4f})\n")


# =============================================================================
# 2. 선정된 최고 모델에 대해 GridSearchCV (하이퍼파라미터 튜닝)
# =============================================================================
from sklearn.model_selection import GridSearchCV

# 승리한 모델에 맞춰 파라미터 세팅
if best_model_name == "RandomForest":
    base_model = RandomForestRegressor(random_state=42)
    param_grid = {
        'n_estimators': [50, 100, 150], 
        'max_depth': [6, 8, 10]
    }
elif best_model_name == "XGBoost":
    base_model = XGBRegressor(random_state=42)
    param_grid = {
        'n_estimators': [50, 100, 150],
        'max_depth': [3, 5, 7],
        'learning_rate': [0.01, 0.1]
    }
elif best_model_name == "LightGBM":
    base_model = LGBMRegressor(random_state=42)
    param_grid = {
        'n_estimators': [50, 100, 150],
        'max_depth': [3, 5, 7],
        'learning_rate': [0.01, 0.1]
    }


grid_search = GridSearchCV(
    estimator=base_model, 
    param_grid=param_grid, 
)

print("하이퍼파라미터 탐색 시작")
grid_search.fit(X_tr, y_tr)

print("가장 좋은 파라미터 조합:", grid_search.best_params_)
# 출력할 때 다시 마이너스를 떼고 원래의 양수 오차 값으로 보여줍니다.
print("그때의 최저 오차(RMSE):", -grid_search.best_score_) 

# 가장 똘똘한 최종 모델 저장
final_best_model = grid_search.best_estimator_


# =============================================================================
# 3. 전체 훈련 데이터로 최종 학습 및 결과 제출
# =============================================================================
print("전체 데이터 최종 학습 및 예측 ---")

# 쪼개기 전의 전체 훈련 데이터(X_train, y)로 최종 학습
final_best_model.fit(X_train, y)

# 평가용(Test) 데이터 예측 (연속된 숫자가 예측됨)
pred = final_best_model.predict(X_test)

# 제출 형식에 맞게 데이터프레임 만들기 (문제에서 요구하는 컬럼명 확인 필수!)
result = pd.DataFrame({"pred": pred})

# csv 파일 저장 (index=False 잊지 마세요!)
result.to_csv("result.csv", index=False)

print(pd.read_csv("result.csv").head())

 

 

 

# 분류 

# 전처리 진행한 상황이라는 전제

# 검증 데이터 분리
from sklearn.model_selection import train_test_split
X_tr, X_val, y_tr, y_val = train_test_split(
    X_train,  # 레이블한거
    y,
    random_state=42,
    stratify=y # 분류일때만
)

# =============================================================================
# 1. 3가지 모델 성능 비교 및 최우수 모델 선정
# =============================================================================
from sklearn.ensemble import RandomForestClassifier
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.metrics import f1_score

# 사용할 3가지 모델을 딕셔너리 형태로 준비합니다.
# - RandomForest와 LightGBM은 class_weight="balanced" 로 데이터 불균형을 잡아줍니다.
# - XGBoost는 다중 분류(0, 1, 2)를 자동으로 인식하며, eval_metric 경고를 없애기 위해 옵션을 추가합니다.
# - LightGBM은 불필요한 출력 메시지를 숨기기 위해 verbose=-1 을 설정합니다.
models = {
    "RandomForest": RandomForestClassifier(random_state=42, class_weight="balanced"),
    "LightGBM": LGBMClassifier(random_state=42, class_weight="balanced"),
    "XGBoost": XGBClassifier(random_state=42)

}

best_model_name = ""
best_score = 0

print("--- [1단계] 기본 모델 성능 비교 (Macro F1 Score) ---")
# 준비한 3가지 모델을 하나씩 꺼내서 학습시키고 점수를 확인합니다.
for name, model in models.items():
    # 학습 데이터로 모델 학습
    model.fit(X_tr, y_tr)
    # 검증 데이터로 예측 수행
    pred_val = model.predict(X_val)
    # 평가지표인 Macro F1 점수 계산
    score = f1_score(y_val, pred_val, average="macro")
    print(f"{name} 모델 Macro F1 점수: {score:.4f}")
    
    # 이전 모델보다 점수가 높다면, 최고 점수와 최고 모델 이름을 갱신(업데이트)합니다.
    if score > best_score:
        best_score = score
        best_model_name = name

print(f" 가장좋은모델 모델: {best_model_name} (최고 점수: {best_score:.4f})\n")

# =============================================================================
# 2. 선정된 최고 모델에 대해 GridSearchCV (하이퍼파라미터 튜닝) 수행
# =============================================================================
from sklearn.model_selection import GridSearchCV

# 앞서 1차전에서 승리한 모델이 무엇인지에 따라 탐색할 파라미터(옵션)를 다르게 설정합니다.
if best_model_name == "RandomForest":
    base_model = RandomForestClassifier(random_state=42)
    param_grid = {
        'n_estimators': [50, 100, 150], # 만들 나무의 개수
        'max_depth': [6, 8, 10]         # 나무의 최대 깊이 (과적합 방지)
    }
elif best_model_name == "XGBoost":
    base_model = XGBClassifier(random_state=42)
    param_grid = {
        'n_estimators': [50, 100, 150], # 학습 반복 횟수
        'max_depth': [3, 5, 7],         # 나무의 깊이 (부스팅 모델은 보통 얕게 설정합니다)
        'learning_rate': [0.01, 0.1]    # 학습률 (업데이트 속도)
    }
elif best_model_name == "LightGBM":
    base_model = LGBMClassifier(random_state=42")
    param_grid = {
        'n_estimators': [50, 100, 150],
        'max_depth': [3, 5, 7],
        'learning_rate': [0.01, 0.1]
    }


grid_search = GridSearchCV(
    estimator=base_model, 
    param_grid=param_grid, 
    cv=5, 
    scoring='f1_macro', 
)

print("--- [2단계] 하이퍼파라미터 탐색 시작 ---")
# 쪼개두었던 훈련용 데이터(X_tr, y_tr)를 넣고 모든 조합을 테스트합니다.
grid_search.fit(X_tr, y_tr)

# 탐색 결과 출력
print("\n가장 좋은 파라미터 조합:", grid_search.best_params_)
print("그때의 최고 점수(교차검증 평균 F1 Macro):", grid_search.best_score_)

# 튜닝이 완료된 가장 똑똑한 최종 모델을 변수에 저장합니다.
final_best_model = grid_search.best_estimator_

# 우리가 빼두었던 검증 데이터(X_val)로 최종 모의고사를 봅니다.
final_val_pred = final_best_model.predict(X_val)
print("튜닝 후 검증 데이터(X_val) 최종 Macro F1 점수:", f1_score(y_val, final_val_pred, average="macro"))


# =============================================================================
# 3. 전체 훈련 데이터로 최종 학습 및 결과 제출 (시험 제출용)
# =============================================================================
print("전체 데이터 최종 학습 및 예측")

# 모델이 더 많은 데이터를 보고 배울 수 있도록, 
# 쪼개기 전의 전체 훈련 데이터(X_train, y)를 다시 집어넣고 최종 학습시킵니다.
final_best_model.fit(X_train, y)

# 진짜 시험지(test) 데이터의 정답을 예측합니다.
pred = final_best_model.predict(X_test)

# 제출 형식에 맞게 데이터프레임으로 묶어줍니다. (컬럼명 'pred' 확인!)
result = pd.DataFrame({"pred": pred})

# csv 파일로 저장합니다. (index=False는 필수입니다!)
result.to_csv("result.csv", index=False)

# 제대로 만들어졌는지 마지막으로 확인합니다.
print(pd.read_csv("result.csv").head())

 

 

파라미터 기억안나면 이렇게 항목들 확인가능 

from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
help(model)
from sklearn.model_selection import GridSearchCV
help(GridSearchCV)

728x90
728x90

 

Product Requirements Document · v2

DCbookspace — 교회 장소 사용 신청·결재 시스템

종이 신청서를 유지하되, 웹에서 현황판을 볼 수 있도록

Project
DCbookspace
Version
v2 · MVP 2차 운영
PRD 작성
2026-05-08

1 개요

교회 시설(예배실·교육실·회의실 등)의 사용 신청과 다단계 결재를 디지털화하는 시스템. 종이 양식 + 도장 회람의 흐름을 그대로 보존하면서 사무실 발걸음·종이 분실·정체·중복 신청을 제거한다.

미션 — 기존 종이시스템 + QR코드, 어르신 결재자가 추가 학습 없이 그대로 쓸 수 있어야 한다. 신청자는 사무실까지 안 가도 되고, 결재 흐름은 그대로 유지된다.

2 페인포인트

실제 운영에서 부딪힌 문제와 본 시스템의 해결 방향:

기존 문제
장소사용신청 하려면 사무실까지 와야
해결
웹에서 신청서 작성 → 사무실 프린터에서 자동 출력. 신청자는 한 발짝도 움직일 필요 없음.
기존 문제
동일 시간·호실 중복 신청 발견 못 함 — 행사 당일 충돌
해결
신청 시점에 즉시 충돌 알림 + 그날 빈 시간대 추천. 강제 진행 시 관리자 검토 플래그.
기존 문제
빈 시간·빈 호실이 한 눈에 안 보임 — 사무실에 전화로 확인
해결
현황판 — 캘린더(날짜별 6주) + 건물 평면도(장소별). 두 뷰를 토글/스와이프로 전환.

디지털화의 진짜 제약

결재자 평균 연령 60대 후반. 웹에서 전자결재는 사실상 불가능.
→ 종이 형태와 결재 라인은 그대로 유지. PIN 4자리(휴대폰 뒷자리)로 식별만 디지털.

3 역할별 요구사항

신청자 / 결재자 / 관리자 + 운영 인프라 요건을 분리해서 정리.

신청자 사무실에 안 가고 끝낸다

  • 웹에서 신청 시 사무실 프린터로 자동 출력 5/9 MVP3
  • 프린트 출력 상태 모니터링 — 출력 중 / 출력 완료 / 출력 오류 DB 컬럼·상태 머신 완료
  • 본인 + 다른 사람 신청 내역 모두 확인 (전체 공개) 완료
  • 결재 진행 상황 현황판에서 즉시 확인 완료
  • 정기(주간 반복) + 다중 시간대 신청 가능 완료
  • 이미 신청된 예약 + 고정 스케줄(주일 예배 등) 표시 + 그래도 신청 가능 완료

결재자 종이 그대로, 도장만 PIN으로

  • 기존 종이 양식 + 결재 라인 그대로 유지 완료
  • QR 안하고 그냥 수기결재해도됨 -> 마지막 관리자가 올리는구조 완료
  • 본인 휴대폰 뒷 4자리 = 초기 PIN (외울 필요 없음) 완료
  • QR 1번 찍으면 → 장소·시간·목적 + 지금까지의 결재 라인 진행도 표시 완료
  • PIN 활성화 후 5분 동안 다른 신청서도 PIN 재입력 없이 자동 결재 완료

관리자 한 화면에서 모든 흐름 통제

  • 달력으로 날짜별 / 장소별 현황 파악 가능 완료
  • 현황판에서 강제 예약 / 신청서 삭제 기능 완료
  • 마스터 계정 + PIN — 중간 결재자가 PIN 잊었을 때 우회 완료
  • 웹에서 월별 / 전체보기로 호실·시간 즉시 파악 완료
  • 모든 신청 내역 엑셀(CSV) 다운로드 예정

추가 인프라 외부 연동·자동화

  • 신청 정보 API 공개 — 외부에서 공간 비어있는지 확인 예정
  • 웹훅 자동 알림 — 서버 이상, 결재 완료, 출력 오류 등 webhook.ts 일부 구현
  • 프린트 큐 연동 — 시놀로지 NAS(420+) 도커 컨테이너에서 사무실 프린터(Sindoh d450) 제어 5/9 MVP3

4 개발 타임라인

의식 → PRD → MVP 반복 업데이트. 약 2주 만에 운영 가능 수준 도달.

  • 2026-04-24 문제 의식 발생 교회 사무실 종이 신청서 흐름의 페인포인트 정리.
  • 2026-05-01 PRD 1차 관리사무소 요구사항 정리. 결재 라인·PIN 체계·QR 토큰 설계.
  • 2026-05-05 PRD 2차 + MVP 1차 관리사무소 요구사항 추가 정리. 신청 폼·결재 흐름·관리자 페이지 기본 동작.
  • 2026-05-06 PRD 3차 + MVP 2차 관리실 요구사항 정리. 부서 2뎁스 트리·관리자 마스터 PIN·시리즈 신청·고정 행사·인쇄 진행 트래킹.
  • 2026-05-07 시놀로지 NAS 사양 확인 → 프린트 자동화 가능 판정 사무실 NAS = Synology DS420+. 도커 컨테이너 가능 → 프린트 큐 에이전트 구동 가능. 사무실 프린터: Sindoh d450.
  • 2026-05-09 MVP 3차 — 프린트 자동화 신청서 작성 → 사무실 NAS 도커 → Sindoh d450 자동 출력 → 프린트 상태 콜백. 이 단계가 끝나면 의도한 플로우가 온전히 진행됨.

5 핵심 사용자 흐름

5-1. 신청 → 자동 인쇄 → 결재 (목표 플로우)

[신청자] /apply 진입 → 부서·호실·일시·목적 입력
   ↓ 충돌 검사 (실시간) — 기존 예약 + 고정 행사 + 빈 시간 추천
   ↓
신청서 1장 발급 (ref_no = "26-0042" + QR 토큰 1개)
   ├─→ 사무실 NAS 도커 → Sindoh d450 자동 출력 ← MVP3
   └─→ 신청자 화면: 출력 진행 모니터링 (출력중 → 완료 / 오류)
   ↓
[결재자] 종이 양식의 QR 스캔 → /sign/[token]
   ├─ PIN 4자리 (휴대폰 뒷자리) → 본인 단계 자동 승인
   ├─ 5분 안에 다른 신청서도 PIN 없이 결재
   └─ admin role PIN 또는 0000 → 어떤 단계든 강제 승인
   ↓
모든 단계 승인 → status='approved' 확정
   └─→ 신청자에게 결과 알림 (카카오 알림톡 + SMS, 예정)

5-2. 정기(시리즈) 신청

  • 매주 같은 요일·시간대 반복 (예: 매주 일요일 14:00~16:00 1청년회 모임)
  • 시작일·종료일 + 요일 + 시간 블록 입력 → 회차 자동 생성
  • 결재 1회로 시리즈 전체 확정

5-3. 신청 수정/취소 (신청자)

  • 1단계 결재 시작 전까지만 본인 수정·삭제 가능
  • 본인 인증: 신청 시 입력한 휴대폰 번호 매칭

5-4. 결재 취소 (당회장 권한)

  • 모든 단계 끝난 신청서를 다시 검토하고 싶을 때
  • 당회장 PIN으로 취소 → 모든 approval 초기화 + reservation status='pending'

5-5. 운영자 비상 경로

  • 마스터 키 0000 (비상용, 코드 하드코딩)
  • 관리자 PIN (role='admin' 사용자, 휴대폰 뒷 4자리)
  • 강제 예약 (결재 우회 즉시 확정) / 신청서 삭제
  • 관리자 비밀번호 분실 시: 010-9654-5448 직접 연락

6 기능 명세 + 구현 상태

6-1. 신청 폼 /apply

  • 부서 cascading select (대분류 9 → 소분류 약 62개 leaf) 완료
  • 호실 cascading (건물 → 층 → 호실) 완료
  • 일회성 / 정기 토글 완료
  • 휴대폰 자동 포맷 + 010 뒤 8자리 필수 검증 (client + server) 완료
  • 날짜 자동 포맷 + 월/일 범위 자동 보정 (윤년 반영) 완료
  • 충돌 검사 + 빈 시간대 추천 + 강제 진행 옵션 완료
  • 고정 행사 충돌도 함께 감지 완료

6-2. 결재 화면 /sign/[token]

  • QR 토큰 1개로 모든 단계 공유 완료
  • PIN 4자리 (bcrypt 해시) 완료
  • 5분 자동 세션 쿠키 완료
  • PIN 오답 시 0.45초 흔들림 + 빨간 강조 + 즉시 비움 완료
  • PIN 잠금 정책 (5회 실패 → 10분 잠금) 컬럼 존재 · 활성화 예정

6-3. 현황 보기 /

  • 날짜별: 캘린더 6주 그리드, 마우스 휠 ±7일, 모바일 스와이프 완료
  • 장소별: 건물 평면도 + 호실 점유 색·아이콘·텍스트 완료
  • 두 뷰 토글 + 좌우 스와이프 + 세션 기억 완료

6-4. 신청 목록 /reservations, /admin/reservations

  • 정렬 7가지 (신청번호·작성일·부서·장소·사용일시·상태·결재 라인) 완료
  • 결재 라인 정렬: 마지막 통과 단계 기준 (당회장 → 관리장로 → 차장 → 부서장 → 대기) 완료
  • 검색: 신청번호·부서명·신청자명 통합 (대시·#·공백 무시) 완료
  • 충돌 그룹 번호 칩 완료
  • 엑셀(CSV) 다운로드 예정

6-5. 관리자 /admin/*

  • BasicAuth + DB-stored 비밀번호 (env 비상 키 영구 유효) 완료
  • 신청서 강제 확정·삭제·결재 취소 완료
  • 결재자 관리 (PIN 발급, 신청 이력 있으면 soft delete + PIN 무효화) 완료
  • 관리자 정보 (다중 마스터 PIN, 최소 1명 보장 — 시드 "홍길동") 완료
  • 부서 트리 관리 (좌측 그룹 탭, leaf 드래그앤드롭 순서 변경) 완료
  • 호실 관리 (도면 좌표 드래그앤드롭 + 리사이즈) 완료
  • 고정 행사 관리 완료
  • 인쇄 진행 상태 모니터링 UI 완료 · NAS 에이전트 5/9

6-6. 외부 연동 예정

  • 공간 가용 여부 조회 API (Read-only) — 다른 시스템에서 사용 가능
  • 웹훅 — 결재 완료, 출력 오류, 서버 이상 알림 (n8n / Slack / Telegram)
  • 카카오 알림톡 + SMS fallback (NCP SENS 또는 SOLAPI)

7 비기능 요구사항

7-1. UX (어르신 친화 — 절대 원칙)

  • 루트 폰트 17px (Tailwind 기본 16px 아님)
  • 모든 터치 타겟 44px 이상
  • 상태 표시는 색 단독 금지 — 항상 색 + 아이콘 + 텍스트 다중 신호
  • 모달은 최소화. 버튼 라벨은 동작 그대로 ("결재 취소", "강제 승인" — "확인" 금지)
  • 입력 검증은 거부가 아닌 자동 보정 우선 (휴대폰·날짜 자동 포맷)

7-2. 보안 불변식

  • /admin/* BasicAuth (server actions POST 포함)
  • ADMIN_PASSWORD 빈 값이면 503 (실수로 보호 풀린 채 배포 방지)
  • SUPABASE_SERVICE_ROLE_KEY 서버 전용
  • 마스터 키 0000 코드 하드코딩 유지 (비상용, 절대 제거 금지)
  • PIN은 bcrypt 해시. 평문 DB 저장 금지

7-3. 성능

  • 홈 페이지 TTFB < 1초 (Suspense streaming + React cache() 메모화)
  • 달력 네비 시각 피드백 (useTransition isPending opacity)
  • BuildingView dynamic import (탭 진입까지 ~30~40KB 절약)
  • DB 인덱스: reservations(start_at, end_at) 부분 인덱스, reservation_series(created_at desc)

7-4. Realtime

  • 관리자 / 신청 상세 페이지: rooms · reservations · approvals 구독
  • 홈은 조회 전용이라 구독 없음 (서버 부하·연결 비용 절약)

8 시스템 아키텍처

[신청자/결재자 브라우저]
    │
    ▼
[Vercel — Next.js 16 / Turbopack]
  ├─ Server Components (데이터 fetch)
  ├─ Server Actions (mutation)
  └─ Proxy 미들웨어 (BasicAuth)
    │
    ▼
[Supabase Tokyo region — Postgres + Realtime]
  ├─ buildings / floors / rooms
  ├─ departments (parent_id self-ref · 2뎁스)
  ├─ users (PIN bcrypt · role enum)
  ├─ reservations / reservation_series
  ├─ approvals (signature_token)
  ├─ approval_routes (steps jsonb)
  ├─ fixed_events
  └─ Realtime publication (rooms·reservations·approvals)
    │
    ▼ (5/9 MVP3 — 신규 경로)
[사무실 시놀로지 NAS · DS420+ 도커]
  ├─ Print queue agent (HTTP poll)
  ├─ Sindoh d450 드라이버
  └─ 출력 상태 콜백 → /api/print/status
    │
    ▼
[외부]
  ├─ 카카오 알림톡 / SMS (NCP SENS or SOLAPI)
  └─ n8n / Slack / Telegram webhook

9 데이터 모델

테이블 핵심 컬럼 비고
buildings / floors / rooms name, display_order, map_x/y/w/h(rooms) 호실 좌표는 0~100% 비율
departments name, parent_id, dept_head_id, elder_id 2뎁스 트리. 결재 라인은 leaf만
users name, phone, role, dept_id, pin_hash, active role: applicant·dept_head·elder·manager·senior_pastor·admin
approval_routes name, steps (jsonb), conditions "기본"·"대규모/외부행사" 두 템플릿
reservations ref_no, qr_token, room_id, applicant_id, dept_id, start_at, end_at, purpose, status, current_step, force_overlap, print_status print_status: requested / printing / completed / failed
reservation_series weekday, start_date, end_date, time_blocks 매주 반복. 자식 reservations 자동 생성
approvals reservation_id (or series_id), step_order, role, approver_id, status, signature_token, comment step_order별 1행
fixed_events name, weekday, start_time, end_time, room_id, effective_from/until 결재 없는 정규 일정

10 권한 매트릭스

동작 신청자 결재자 당회장 관리자 마스터 0000
신청 작성 + 자동 인쇄
본인 신청 수정 (1단계 전)
본인 단계 결재
어떤 단계든 강제 승인
결재 취소 (모든 단계 reset) (사무처)
/admin/* 접근

11 성공 지표 (KPI)

지표 측정법 1차 목표
사무실 직접 방문 신청 비율 사무처 추적 (전체 신청 중 종이 비율) 3개월 내 0%
신청서 평균 결재 완료 시간 created_atstatus=approved 24시간 이내 (종이 대비 1/3)
신청 시점 충돌 감지율 충돌 모달 노출 / 실제 중복 신청 95%+
자동 인쇄 성공률 print_status=completed / 전체 98%+ (5/9 이후)
어르신 결재 완료 자력률 월 1회 인터뷰 80%+
운영자 강제 개입 빈도 comment LIKE '관리자 마스터%' 월 5회 이하

12 로드맵

5/9 MVP 3차 (확정)

  • 프린트 자동화 — 시놀로지 DS420+ 도커 + Sindoh d450 출력 + 상태 콜백

다음 분기

  • 결재 결과 알림 — 카카오 알림톡 + SMS fallback (NCP SENS 또는 SOLAPI)
  • 엑셀(CSV) 다운로드 — 모든 신청 내역 일괄 export
  • 외부 공간 조회 API — Read-only 엔드포인트 (다른 교회 시스템·키오스크 연동)
  • PIN 잠금 정책 활성화 — 5회 실패 → 10분 잠금 (DB 컬럼 이미 존재)
  • 관리자 페이지 검색 — 결재자/관리자/호실 통합 검색
  • 결재선 템플릿 UI — 현재 DB 직접 편집

향후

  • Audit Log — 강제 승인·결재 취소 등 민감 작업 추적
  • 벌크 작업 — 신청서 일괄 승인/삭제
  • 카톡 공유 버튼 — 결재 링크 공유 단축



728x90

'글적글적 > 방향성' 카테고리의 다른 글

[창업하기전에 알아야할 PM 지식]  (1) 2023.12.06
취업 방향  (0) 2023.02.20
개발 공부를 하게된 이유, 해야 하는 이유  (0) 2022.12.06
728x90

미디어 강사로 미디어리터리시 수업을 자주하기도했고,

정보의 바다에서 가짜뉴스의 위험성을 누구보다도 잘 알고 있었기에 베팅온 팩트의 구성과 기획을 눈여겨봤다.

그러던중 7편의 [뉴스 헤드라인] 10번문제에서
도저히 이해가 되지않는 결과로 찾아보게되었다.

 

우선 해당 게임은
뉴스의 헤드라인만으로 뉴스의 진위 판단 후 팩트인지 거짓인지 정답을 맞추는 게임이다.
(이런 헤드라인이 있었냐 없었냐의 게임이였다면 이해됐을텐데)

 

위고비 미 항공업계 연료비절감 8500억 줄였다? 라는것을 FACT 라고하길래 찾아봤다.




하지만 그어떤 뉴스기사에도
위고비로 미 항공업계 연료비절감 8500억 "줄였다" 라고 한 곳은 존재하지 않았다.
https://www.donga.com/news/Inter/article/all/20260119/133185183/2


이 뉴스 기사에보면 

그 어디에도 줄였다라고 확정적으로 말하지 않고, 추정된다, 전망된다 라는 말만 쓰고 있지만

정작 헤드라인은 마치 그 추정치가 현실에서 이루어진것 마냥 "줄여"라는 표현을 쓴다.
뭐 이러니깐 내가 쓰레기 같은 뉴스를 잘 안보고 차라리 믿을만한 유튜버를 보고 판단하는데

 

 

팩트체크를하는 방송에서? 이런 가짜뉴스를 팩트라고 하길래 도저히 납득이 되지않는다.

728x90
728x90

 

필자는 m1 max 32G에 openclaw + 로컬 qwen3.5 (feat; ollama)를 설치하려고한다

 

4090처럼 딥하게 쓸건아니고 나중에 NAS에 도커로 클라우드 api로도 테스트하기전에
딱 그 중간에서 아 m1x로 이정도 성능이 나오는구나 각 나오면 맥 스튜디오 사야지하고 우선 테스트용으로 설치를 해본다.

목적 자체는 SBC(Tachyon) 에서 IMX519 받은 이미지를 (차량 ALPR) 처리할 서버로 사용할 예정이며,
m1x 자체가 전력대비 성능이 좋아서 24시간으로 일단 한번 테스트
그래서 로컬 openclaw + 로컬로 모델을 돌릴 ollama를 설치할 예정

 


1. Ollama 설치
올라마 서버를 먼저 띄우고 나중에 오픈클로 설치하면서 바로 연동예정
Terminal 열고 이 한줄이면 끝

https://ollama.com/

curl -fsSL https://ollama.com/install.sh | sh



설치가 다됐으면 

ollama


라고 입력하고 나는 로컬로 qwen3.5 선택 (ALPR는 gemma4 보다는 qwen3.5가 좋음)

 

 

 

2. ollama launch openclaw

 

 

 

3. 설치 끝

뭐야 거의 1분만에 설치가 끝나버림;;

 

 

 

 

pip install asitop

sudo asitop

728x90

'Network > [Automation]' 카테고리의 다른 글

Openclaw Windows 도커로 설치하기  (0) 2026.04.10
AI agent (feat n8n+synology nas)  (0) 2025.11.20
728x90

지금까지 공부한것을 바탕으로 

정부지원사업에 뛰어들어봄 
컴퓨터비전관련공부(CCTV를 통한 무인매장) + 영상관련 + PG 관련해서 뭐가 좋을까하다가 
주차관제 + 주차공유플랫폼 결합이라는 내가 이전부터 관심을 가졌던 분야로 지원하기로함!

일단 목표가 생겨서 공부하기가 편함!




https://www.modoo.or.kr/

 

모두의 창업

내일을 움직이는 우리의 창업, 멘토링부터 시제품 제작, 사업화까지 전과정을 지원하는 국가 차원의 창업프로젝트

www.modoo.or.kr

 

 

일반/기술 분야  그리고 로컬 분야가 있음!
일단 나의 목표는 1라운드 정도는 통과하고 싶다는 생각이 들었음!!  

 

 

 

보니 지원방법도 굉장히 간단하다!

이젠에 괜찮은 아이디어가 있었지만, 아 이걸 어떻게 사업화해야할까 고민많이 했는데

이런 기회가 있으니 너무 좋다!!

 

 

 

 

 

 

 


자세한 내용은 1라운드 시작하면 본격적으로 써보도록 하겠음다!

728x90

'글적글적' 카테고리의 다른 글

아이폰 VS 갤럭시  (0) 2024.02.21
[전세보증보험] 주소가 안뜬다면?  (0) 2023.04.27
728x90

 

필자는 RTX4090 탑제된 windows 에서 도커 데스크톱으로 Openclaw를 설치할 예정이다
도커에 설치하는 이유는 Openclaw가 어떻게 날뛸지몰라서 격리된 환경에서 4090은 사용하되 컴퓨터를 보호하려는 목적이다.

1. WSL 설치 

제어판 → 프로그램 → Windows 기능 켜기/끄기

Linix용 Windows 하위 시스템과 가상 머신 플랫폼 설정을 합니다.

 

 

# Powershell 관리자모드에서 입력 
wsl --install

 

2. 도커설치

https://docs.docker.com/desktop/windows/install

 

3. Nvidia Toolkit 설치
GPU와 도커연결

https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html

 

# 도커환경내에서 GPU 연결상태보기
docker run --rm --gpus all nvidia/cuda:12.1.0-base-ubuntu22.04 nvidia-smi

 

 

4. 도커 데스크톱에서 이미지검색 및 다운로드

vllm, openclaw, npm (나중에 포트관리가 용이하게)

 

 

5. vllm 에서 
다른 커뮤니티보니깐 4090이면 
https://huggingface.co/google/gemma-4-26B-A4B-it 8비트도 돌아간다고하는데


필자는 gemma4 26b-8bit 다운로드받다가 GPU 메모리부족으로 8비트를 포기하고 4비트로 가기로결정 

https://huggingface.co/cyankiwi/gemma-4-26B-A4B-it-AWQ-4bit

 

 



# 2. max-model-len을 32768로 설정하여 실행
docker run -d --gpus all `
      --name vllm-gemma4 `
      --restart always `
      -v ${HOME}/.cache/huggingface:/root/.cache/huggingface `
      --env "HUGGING_FACE_HUB_TOKEN={당신의 허깅페이스 토큰번호}" `
      -p 8000:8000 `
      --ipc=host `
      --entrypoint /bin/sh `
      vllm/vllm-openai:latest `
      -c "apt-get update && apt-get install -y git && pip install git+https://github.com/huggingface/transformers.git && python3 -m vllm.entrypoints.openai.api_server --model cyankiwi/gemma-4-26B-A4B-it-AWQ-4bit --max-model-len 32768 --gpu-memory-utilization 0.95 --trust-remote-code --host 0.0.0.0 --served-model-name gemma4 --enable-auto-tool-choice --tool-call-parser hermes"

 

http://localhost:8000/v1/models

docker logs -f vllm-gemma4

# 모델이 제대로 설치되었는지 확인
curl http://localhost:8000/v1/models

 

 

 

6. Openclaw 설치

도커에서 openclaw 이미지(openclaw:local)를 다운받은다음에 

opershell 에 다음 명령어 입력

docker run -d --name openclaw-gateway `
  -p 18789:18789 `
  --env GATEWAY_BIND=0.0.0.0 `
  --env GATEWAY_PORT=18789 `
  --env GATEWAY_MODE=full `
  --env OPENAI_API_BASE=http://host.docker.internal:8000/v1 `
  --env OPENAI_API_KEY=none `
  --add-host=host.docker.internal:host-gateway `
  --restart always `
  openclaw:local

 

설치가 다 되면

도커에 들어가서 openclaw onboard 입력

또는 어딘지 모르겠으면 그냥 파워쉘에서

# Powershell 에서 도커명령어
docker exec -it openclaw-gateway openclaw onboard

입력해도 도커에서 돌려줌

 

docker logs -f openclaw-gateway 라고 해주면 로그가 쭉음

 

 


baseurl 에는
http://host.docker.internal:8000/v1

 

 

7.  127.0.0.1 바인딩해결하기

curl http://127.0.0.1:18789

이렇게 바인딩이 안되있는 경우가 있음

이런 경우 실행중인 Containers > Files로 접근하여서
home > node > .openclaw > openclaw:json 을 우측 클릭하여 edit file

 쭉내리면  gateway 설정이있다

{
  "gateway": {
    "bind": "0.0.0.0",   // <--- 여기가 루프백으로 되어 있다면 무조건 0.0.0.0으로 수정! 또는 "lan" 으로 수정
    "port": 18789,
    "controlUi": {
      "allowInsecureAuth": true  // <--- 이 설정이 있어야 브라우저 접속을 허용됨
    }
  }
}

 

 

8  Pairing

마지막으로 openclaw dashboard 입력하거나 
설치가 다 끝나면 링크+토큰 번호를 주는데 해당 링크를 누르면 이렇게 뜸

 

 

 

docker exec -it {컨테이너이름} dist/index.js devices list


입력하면 디바이스 리스트를 쭉 알려줌 거기서 디바이스 리스트 복사한다음에


docker exec -it {컨테이너이름} dist/index.js devices approve {devices list}

docker exec -it {컨테이너이름} dist/index.js devices approve {devices list}


나의경우
docker exec -it openclaw-gateway dist/index.js devices approve 7e16ebe2-661e-461b-aff4-d986f46bef12

728x90

'Network > [Automation]' 카테고리의 다른 글

Openclaw 맥북에 설치하기  (0) 2026.04.29
AI agent (feat n8n+synology nas)  (0) 2025.11.20
728x90

https://www.kickstarter.com/projects/particle-iot/tachyon-powerful-5g-single-board-computer-w-ai-accelerator

컴퓨터비전용 SBC 장난감을 펀딩했고
드디어 배송을 받았다~!

IMX 591은 오고있는중

나중에 까먹지않기 위해 설치방법을 기록하려고함.


1. 설치를 위한 1차 준비
https://developer.particle.io/tachyon/setup/install-setup

 

 

Install and Setup | Particle Developer

Let’s get your Tachyon up and running! 🚀

developer.particle.io

 

 

1. 컴퓨터에서 npm 및 particle CLI 설치 https://docs.particle.io/getting-started/developer-tools/cli/

Particle CLI 설치 

# Particle CLI
bash <( curl -sL https://particle.io/install-cli )

# 업데이트 진행 
particle update-cli

# 버전확인
particle --version

 

 

 

2. 장비 프로그램 모드 전환

 

 

 

 

 

 

# 전원버튼 3초이상 꾹 누르면 노란색으로 LED 바뀜
# usb 확인
particle usb configure

# Tachyon 설치
particle tachyon setup

# 단계 쭈욱 이어가면됨!

 

 

# 설치가 다되면 이렇게 뜸

All done! Your Tachyon device is ready to boot to the desktop and will automatically connect to Wi-Fi.

To continue:
  - Disconnect the USB-C cable
  - Connect a USB-C Hub with an HDMI monitor, keyboard, and mouse.
  - Power off the device by holding the power button for 3 seconds and releasing.
  - Power on the device by pressing the power button.

When the device boots it will:
  - Activate the built-in 5G modem.
  - Connect to the Particle Cloud.
  - Run all system services, including the desktop if an HDMI monitor is connected.

Learn more about Tachyon at our developer site: https://developer.particle.io/tachyon

View your device on the Particle Console at: https://console.particle.io/tachyon-번호/devices/장비번호

# 다시 부팅하면
전원 led가 보라색으로 뜰거임

 

 

 

혹시나 문제가 생겼다면 초기화하고 다시진행!
https://developer.particle.io/tachyon/troubleshooting-and-tricks/restore



# 이제 591 카메라 붙이러가야지~

 

https://setup.particle.io/

728x90

'Server > [SBC]' 카테고리의 다른 글

[Tachyon] Powerful 5G single-board computer w/ AI accelerator  (0) 2025.06.17
728x90

성능 및 시놀 작업을 위해서 
NUC에 n8n 다시 설치 중

 

https://www.youtube.com/watch?v=A2xUp8qz9ps

 

1. Create CT 누르기

2. Host name 

 

1. apt update && apt upgrade -y 

2. apt install -y ca-certificates curl gnupg lsb-release 

3. curl -fsSL https://get.docker.com | sh 

 

4. docker --version 

5. STOP and go to Host shell  -- pct stop {자신의 컨테이너 번호} 

 

 

6. nano /etc/pve/lxc/ {자신의 컨테이너 번호} .conf 

 

7. lxc.apparmor.profile: unconfined lxc.mount.auto: proc:rw sys:rw 

 

Ctr + o , enter Ctr + X 

 

 

8. pct start  {자신의 컨테이너 번호} 

 

 

10. mkdir -p /opt/n8n mkdir -p /opt/n8n/data

11. ls -la /opt

12. chown -R 1000:1000 /opt/n8n

 

13. ls -la /opt/n8n

14. cd /opt/n8n

15. nano docker-compose.yml

 

16.

version: "3.8"

services:
  n8n:
    image: n8nio/n8n:latest
    container_name: {CT name} #n8n
    restart: always
    ports:
      - "5678:5678"

    environment:
      - N8N_HOST={자신의 HOST URL} # n8n.chanuk.theworkpc.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL={자신의 HOST URL} # https://n8n.chanuk.theworkpc.com/

      - NODE_ENV=production
      - GENERIC_TIMEZONE=Asia/Seoul
      - TZ=Asia/Seoul

      # 보안 (필수)
      - N8N_BASIC_AUTH_ACTIVE=true
      - N8N_BASIC_AUTH_USER={ID}
      - N8N_BASIC_AUTH_PASSWORD={PASSWORD}

      # 파일 권한 문제 방지
      - N8N_USER_FOLDER=/home/node/.n8n

    volumes:
      - ./n8n_data:/home/node/.n8n

 

 

Ctr + o , enter Ctr + X

 

17. docker compose up -d

18. docker ps

 

NPM 세팅할때 n8n 경우는 Websocket supports 반드시 ON!

 

728x90
728x90

 

 

 

가끔 쇼핑하다보면 가품을 정품인냥 속여서 판매하는곳이 너무 많다...

진짜 사망여우에서 제보하는 영상 볼때마다 사기를 대놓고 치는데도 쉬쉬하는 기관들을 볼때면 화가 치밀어 오른다.

아무튼 이번에 신발하나 사려고 후기글 보는데  왠걸 블로그 가품 후기글이 있어서 오히려 관심이 가기 시작했다.




 

자 이 문구를 보면 우리는 정품을 판매하는구나 바로 알 수 있다.

(해외병행도 정품임, 가품아님)



 

 

 



https://blog.naver.com/hb1324/222641904796

 

잇썸몰 구매한 나이키 운동화, 더이상의 피해자가 없길 바랍니다(상점명:블레슈→바이잇)

구매후 카톡으로 한번 더 정품인지 확인하였습니다. 상품을 받은 후, 본인이 정품이라고 말한 카톡내용과 ...

blog.naver.com


2022년에 작성된 글인데 3년동안 똑같이 장사를 하고 있다는건? 도대체 해당기관은 뭐하고 있음? 

 

그래 일단 저 블로그 작성자의 말 또한 온전히 믿을 수 없다.
내가 상품을 받아본 것이 아니기 때문에, 우선 정말 가품을 판매하는지부터, 그리고 왜 저 사이트가 3년 동안 무사히 운영될 수 있었는지 파헤치려고 한다.
분명 나처럼 시도한 사람들의 후기를 보고 싶었는데 딱히 없어서 내가 시도해봄.

우선 상품을 구매하기 전에 가품을 받으면 어떻게 되냐고 물어보았다.
애네들 구조를 보아하니 “나 오픈마켓이라 판매자들이 판매하는 거고 나는 중간에서 중개만 했을 뿐이야!” 라는 식으로 꼬리 자르기를 하려는 구조인 듯함.

이때부터 느낌이 쎄함을 느낌 ㅋㅋㅋ

 

 

판매사이트에 정품만 파냐고 문의한 내용의 답변

 

 

 

그래서 직접 판매하는 판매처의 연락처를 알아내서 그 쪽으로 문의를 진행하였더니 더 가관이였다.

"이전에 정품 하나는 비정상적으로 나왔습니다"
그럼 그게 정품이 아닌거잖아? 왜 정품이라는 표현을 쓰는거지?

그래서 상품페이지에 100% 정품이라는 말을 쓰지말랬더니 참고하겠다고 한다 (안바꾸겠다는 소리임)

 

판매처로 문의한 내용

 

 

 

 

 

 

 

 

 

 

 

 

자 일단 느낌만 봐도 가품을 판매한다는것 같다는게 느낌이 확 온다! 

솔직히 정품이 온다면 아무런 문제가 없지만,

정품이라고 광고하지만, 가품이 왔을때 어떤식으로 대처해야할까? (환불만 받는다면 또 이짓거리 할께 뻔하니.. 소송맛을 봐야겠지?)

하는 생각에 적어본다.
https://open.kakao.com/o/gRYd5y5h 
혹시나 해서 적는다. 잇썸몰에서 제품을 구매했고(기록이 남아있어야함), 가품이라는 증거만 찾으시면 이 카톡방에 제보좀

 

 

25/11/26일 주문을 하고 기다려본다

 

 

25/12/04일 상품을 받게되었고,

박스사진은 뭔가 그냥그럼, 파란색 이상한 텍도 있는데 여기까지는 그럴 수 있다고 생각하는데!! 

 

 

 

아니 잉크가 ㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

 

 

 

 

 

 

 

 

 

 

일단 이정도만 되도 가품의 증거가 확실해서 

https://ecrm.police.go.kr/minwon/crs/report_step2

온라인에서 민원을 넣으려고했더니,

사이버사기 > 쇼핑몰 사기의 유형은 이런거라고하네??

 

 

 

일단 접수를 한번 더 눌러서.. 나는 약속한 물품(정품)을 가품으로 받았으니 

 

 

 

 

 

 

확인을 누르니? 응?

 

 

일단 무조건 경찰서 내방을 해야한다... 일단 경찰서를 찾아가야겠군

 

 

+ 25/12/09일 경찰서를 방문하여 사건을 접수하였음

담당자가 정해지면 연락주신다고한다~ 



+ 25/12/10일 
사건 담당자가 연락을 주었고,

우선 가품확인서가 필요하다고 한다.
뉴발란스는 따로 가품판별을 안한다고하니 사설도 괜찮다고한다. + 결제는 어떻게 했냐고 물어보고 카드로 했다고하니깐 이름이 뭐냐고 물어보신다. 카드사 어플통해서 확인해보니 "(주)프롬어스"로 뜬다

가품확인서 서류를 뽑기위해 좀 알아보는 과정이 필요하다.. 

https://laors.co.kr/sub060101.php

좀더 싼데는없나 ㅠㅠ 한번 감정서를 발급받는데 3만원 정도하네 ㅠㅠ
-> 여기는 뉴발란스 신발 정품검정을 안해준다고 한다 ㅠㅠ
-> 고이비토도 마찬가지
FAKEX 연락중인데 답이없음 -> 계속 답이없음


https://www.k-royal.co.kr/


여기에 다시 작성중
12/14 -> 뉴발은 취급하지않는다고 연락옴

12/15일 
사건담당자는 가품소견서가 없으면 진행할 수 없다고 함. 
나는 가품소견서를 받고싶은데 대부분 고가의 상품만 가품확인을 해주어서 업체를 찾지못했다고 말하자, 그냥 취하하라고 한다.
이해는 된다... 형사 입장에서는 얼마나 많은 더 우선순위인 일들이 있을까?
결국 왜 한국에 사기꾼들이 판을 치고 돌아다니는지 시장경제와 공무원들의 업무 이해관계를 보아 바로 이해할 수 있었다.

728x90
728x90

Home assistant를 넘어서 다른것도 자동화해볼까하다가 알게된 여러 AI agent!!

항목 n8n make zapier
요금 구조 Execution 기반 과금 (1회 워크플로우 = 1 execution)
• 클라우드: 월 약 20~60달러(사용량 따라 증가)
자체 호스팅 무료 (서버 비용만 부담)
Operation 기반 과금 (각 모듈 1회 실행 = 1 operation)
• 월 약 10~70달러 (작업량 따라 급증)
Task 기반 과금 (각 액션 = 1 task) • 월 20~100달러 이상 • 높은 사용량 시 매우 빠르게 비용 증가
강점 • 오픈소스 + 자체 호스팅 가능 • JavaScript로 고급 로직 구현 가능 • 복잡한 워크플로우 처리 능력 우수 • 비용 예측 쉬움 (Execution 단위) • 가장 시각적이고 직관적인 UI • 풍부한 내장 모듈
• 데이터를 다루는 매핑·루프 기능 편리
• 비개발자가 쉽게 학습 가능
가장 쉬운 사용성 • 앱 커넥터 수가 가장 많음 • 마케팅·영업 툴 자동화에 적합 • 비기술자 중심 빠른 구축
추천 대상자 • 개발팀 / 엔지니어링 조직 • 보안·프라이버시 중요(온프레미스 필요) • 비용 절감·장기 확장 고려 사용자 • 복잡한 자동화/백엔드 통합 • 비개발자·운영팀 • 시각적 편집이 중요한 조직 • 쉬운 구축이 우선일 때 • 중급 난이도 워크플로우 • 비즈니스 사용자(마케팅, 영업팀) • 아주 간단한 자동화 위주 • 많은 SaaS를 빠르게 연결해야 할 때
호스팅 방식 클라우드 제공 + 자체 호스팅 가능 • Docker, 서버, VPS, k8s 모두 지원 클라우드 전용 • 온프레미스 불가(엔터프라이즈 일부 제외) 클라우드 전용 • 자체 호스팅 불가
확장성 • 서버 확장에 따라 무한 확장 가능 (k8s 등) • 복잡한 조건/분기/병렬 처리 강함 • 커스텀 노드 개발 쉬움 • 클라우드 인프라 자동 확장 하지만 복잡도 증가 시 비용 폭증 가능 • 확장성은 좋으나 비용 증가가 매우 빠름 트리거 지연(폴링 방식) 문제 발생 가능

 

 

n8n을 추천하는 이유

- 자체호스팅할 수 있다면 무료

- 대량/복잡한 자동화에 가장유리함

- 보안에 유리함

- 확장에 유리함

 

-------------

 

시놀로지 나스가 있으니깐 그러면 n8n을 나스에 까는 방법을 알아보자

 

1. Docker 에 설치

메인메뉴 > Container Manager > 레지스트리 > n8n 검색 > n8nio/n8n 다운로드

 

 

다운로드가 끝나면 
이미지 > 실행

 

1. 자동 재시작 활성화 체크(나스가 재부팅 될때, 해당 컨테이너도 같이 재부팅)

2. Web station을 통해 웹포털 설정 (웹 호스팅으로 띄울꺼니깐)

 

다음버튼 >

 

포트설정은 따로할 필요없고

볼륨 설정 > 폴더 추가 > {임의의 폴더} > /home/node/.n8n 입력


 

환경부분

+ 추가 눌러서 변수추가

N8N_HOST   :  n8n.{여러분꺼적으시면됩니다}.synology.me    
N8N_PROTOCOL : https
WEBHOOK_URL :  https://n8n.{여러분꺼적으시면됩니다}.synology.me
N8N_PORT : 5678

 

 

네트워크

host

 

 

 

 

다음누르면 web station이 열림

 

포털 유형 : 이름 기반
호스트이름 n8n.{여러분꺼적으시면됩니다}.synology.me

포트는 80/443 누르시면되는데 저는 이미 80/443 포트 쓰고있어서 대체포트적음 (당연히 포트열어주셔야함)

 

 

 

 

이후

n8n.{여러분꺼적으시면됩니다}.synology.me 또는
n8n.{여러분꺼적으시면됩니다}.synology.me:443(3) 입력시 접속완료!

728x90

'Network > [Automation]' 카테고리의 다른 글

Openclaw 맥북에 설치하기  (0) 2026.04.29
Openclaw Windows 도커로 설치하기  (0) 2026.04.10
728x90

http://insurancesupport.or.kr/durunuri/intro.php

 

두루누리 사회보험

사업주와 근로자 모두에게 희망을 여는 즐거운 소식! 두루누리 사회보험료 지원사업입니다.

insurancesupport.or.kr

 

 

1. 지원대상

  •  근로자 수가 10명 미만인 사업에 고용된 근로자 중 월평균보수가 270만원 미만인 신규가입 근로자와 그 사업주
  •  2021년부터는 신규가입자에 대해서만 지원

2. 지원수준 및 지원기간

  • (지원수준) 신규가입 근로자 및 사업주가 부담하는 고용보험과 국민연금 보험료의 80%
    * 고용보험의 경우 근로자는 월 최대 16,560원, 그 사업주는 월 최대 21,160원까지 지원하며, 국민연금의 경우 근로자와 그 사업주는 각각 월 최대 82,800원까지 지원
  • (지원기간) 2018년 1월 1일부터 신규가입자 및 기가입자 지원을 합산하여 36개월까지만 지원

3. 지원 제외대상

지원 대상에 해당하는 근로자가 아래의 어느 하나라도 해당되는 경우에는 지원 제외됩니다.
  •  지원신청일이 속한 보험연도의 전년도 재산의 과세표준액 합계가 6억원 이상인 자
  •  지원신청일이 속한 보험연도의 전년도(소득자료 입수 시기에 따라 보험연도의 전년도 또는 전전년도) 종합소득이 4,300만원 이상인 자

4. 보험료 지원방법

두루누리 사회보험료 지원을 신청하면 사업주가 월별보험료를 법정기한 내에 납부하였는지를 확인하여 완납한 경우 그 다음 달
보험료에서 해당 월의 보험료 지원금을 뺀 나머지 금액을 고지하는 방법으로 지원하고 있습니다.
(다만, 그 다음 달에 부과될 보험료가 없는 경우에는 해당 월의 지원금은 지원하지 않음)

두루누리 사회보험료의 경우 지원신청일이 속한 달의 고용보험료부터 해당 보험연도 말까지 지원하되, 보험연도 말 현재
고용보험료 지원을 받고 있고 그 보험연도 중 보험료 지원기간의 월평균 근로자인 피보험자 수가 10명 미만인 경우에는 다음
보험연도에 별도로 신청하지 않더라도 계속 지원을 받으실 수 있습니다.
다만, 고용보험료의 경우 사업주가 보수총액신고 또는 피보험자격 취득신고를 법정기한 내에 하지 않은 경우에는 그 신고를 이행한 날이 속한 달의 고용보험료부터 지원하고, 지원대상이 되는 근로자인 피보험자가 일용근로자인 경우에는 사업주가 법정기한 내에 제출한 달의 '근로내용 확인신고서'에 기재된 사람에 대한 월별보험료만을 지원합니다.

5. 지원금액 산정 예시

사업주지원금(신규가입자의 경우)
  • 근로자 수 10명 미만인 사업에 고용된 근로자의 월평균보수가 230만원이라면 매월 103,960원을 지원 받을 수 있습니다.(80% 지원)
근로자지원금(신규가입자의 경우)
  • 근로자 수 10명 미만인 사업에 고용된 근로자의 월평균보수가 230만원이라면 매월 99,360원을 지원 받을 수 있습니다.(80% 지원)

참고사항

근로자 수가 ‘10명 미만인 사업’이란?

  •  지원신청일이 속한 보험연도의 전년도에 근로자인 피보험자 수가 월평균 10명 미만이고, 지원신청일이 속한 달의 말일을 기준으로 10명 미만인 사업
  •  지원신청일이 속한 보험연도의 전년도 근로자인 피보험자 수가 월평균 10명 이상이나 지원 신청일이 속한 달의 직전 3개월 동안
    (지원신청일이 속한 연도로 한정함) 근로자인 피보험자 수가 연속하여 10명 미만인 사업
  •  지원신청일이 속한 보험연도 중에 보험관계가 성립된 사업으로 지원신청일이 속한 달의 직전 3개월 동안(지원신청일이 속한
    연도로 한정하며, 보험관계성립일 이후 3개월이 지나지 아니한 경우에는 그 기간 동안) 근로자인 피보험자 수가 연속하여 10명
    미만인 사업
  • * 근로자 수 산정 시 출산전후휴가, 유산ㆍ사산 휴가, 육아휴직 또는 육아기 근로시간 단축에 해당하는 근로자는 제외하고 산정함
  • * 법인은 법인등록번호, 개인은 사업자등록번호 단위로 사업 규모를 판단함
  • * 「부패방지 및 국민권익위원회의 설치와 운영에 관한 법률」 제2조 제1호에 따른 공공기관은 10명 미만인 사업에 해당하여도 지원대상에서 제외함
728x90
728x90

NAS는 왜 쓸까?

- 데이터 저장 및 백업

- 24/7 구동 및 어디서든 데이터 접근

- 저전력 및 저소음 

NAS 의 미래는 어떻게 될까?

이제 NAS도 그냥 저장만 하는 게 아니라,
AI랑 붙어서 점점 똑똑해지고 있다.

예를 들면,

https://www.kickstarter.com/projects/oricotechs/orico-cyberdata-ai-powered-nas-with-gpu-dock-and-raid-cabinet?ref=section-homepage-view-more-discovery-p1&category_id=Q2F0ZWdvcnktNTI=


https://www.kickstarter.com/projects/zettlab/zettlab-ai-nas-personal-cloud-for-smart-data-management/description

  • 사진들을 원하는 카테고리로 자동으로 분류 및 정리해줌 
  • “강아지 사진 보여줘” 하면 이미지 및 영상을 바로 찾아줌
  • CCTV 영상에서 이상한 움직임 감지
  • 외국어 음성에다가 자동으로 자막 달아주는 것도 가능해짐
  • 데이터, 통계를 빠르게 추출가능 (AI 엣지디바이스의 정보들을 AI NAS로 받아서 쓴다면 정말 많은게 가능해짐)

진짜, 옛날에는 상상도 못 했던 기능들이 점점 현실이 되고 있음.


근데 문제도 있다

NAS는 원래 조용하고 전기 안 먹는 게 장점인데,
AI가 들어가면 얘기가 달라진다.

  • 전기 많이 먹는다.
    AI 연산 돌리려면 고성능 칩이 필요한데, 그만큼 전력도 많이 먹고 발열도 생긴다.
  • 소음도 올라갈 수 있다.
    AI 기능 쓰려다 보면 팬 돌아가고, NAS 가 시끄러워짐

    근데 이영상보니깐 55~65 사이던데 나쁘지 않은데 (시놀 6bay가 55~60사이)
    https://youtu.be/od20jLrWDuI?si=aFJ0f7hpXlM2Vy6L

 

 

 

(Zettlab)
https://www.youtube.com/watch?v=toNhQJPm83Q&t=1297s

 

(Orico) 
https://www.youtube.com/watch?v=p4m4FuLkwYk&t=26s

 

728x90

'ITem' 카테고리의 다른 글

AI 서버용 GPU가 장착된 NAS : Zimacube  (1) 2023.12.05
728x90

뭐 재미난거 만들꺼 없나? 하다가 Kickstarter에서 발견한 SBC 

스펙은 사진으로 대체한다.

 

 

우선 해당 스펙정도면
실시간 영상분석, 사람/차량 감지, 얼굴 인식 등에는 적절히 쓸 수 있는 엣지 디바이스용 AI 추론으로는 준수한 스펙
인데 가격도 160달러정도로 저렴하게 산듯하다.

 

 

 

 

우선 Edge AI를 한번 돌려보려고한다.

카메라 모듈하나 달아서 주차장관리 시스템 간단하게 구현해볼예정

 

 

 

 

 

 

728x90

'Server > [SBC]' 카테고리의 다른 글

Tachyon 초기세팅 방법  (0) 2026.03.03

+ Recent posts