Commit 01b7dfd6 authored by KangMin An's avatar KangMin An
Browse files

Create & Update : 데이터 분석 및 결과 저장 코드 생성 및 문서 갱신.

parent 504e87c9
### _데이터 명세서_ ### _데이터 명세서_
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<br> <br>
# 1. Data Directory Structure # 1. Data Directory Structure
...@@ -19,7 +21,8 @@ ...@@ -19,7 +21,8 @@
∟ YYYYMM (연/월) ∟ YYYYMM (연/월)
∟ YYYYMMDD (연/월/일) ∟ YYYYMMDD (연/월/일)
∟ weather.csv ∟ weather.csv
∟ weights.csv ∟ analysis_parameters.csv
∟ predict_parameters.csv
데이터가 저장되는 경로의 구조입니다. 데이터가 저장되는 경로의 구조입니다.
...@@ -33,7 +36,7 @@ ...@@ -33,7 +36,7 @@
데이터들은 CSV(Comma Separated Values) 형식의 파일로 저장됩니다.<br><br> 데이터들은 CSV(Comma Separated Values) 형식의 파일로 저장됩니다.<br><br>
## Ouside Data ## Ouside Data - weather.csv
외부 데이터는 다음과 같은 형식으로 저장됩니다. 외부 데이터는 다음과 같은 형식으로 저장됩니다.
...@@ -43,7 +46,7 @@ ...@@ -43,7 +46,7 @@
<br><br> <br><br>
## User Side Data ## User Side Data - weather.csv
사용자가 설정한 장소의 데이터는 다음과 같은 형식으로 저장됩니다. 사용자가 설정한 장소의 데이터는 다음과 같은 형식으로 저장됩니다.
...@@ -53,9 +56,27 @@ ...@@ -53,9 +56,27 @@
<br><br> <br><br>
## User Side Data - parameters.csv
Linear Regression을 진행하며 조정된 가중치와 편향 값입니다. 마지막 한개의 값이 편향이며, 이외의 값은 가중치 입니다.
| Weights | … | Bias |
| :-----: | :-: | :--: |
| 가중치 | … | 편향 |
<br><br>
# 3. Data Processing # 3. Data Processing
EUE가 제일 중요하게 수행해야할 부분입니다. 데이터에 대해 선형회귀 분석을 진행합니다. 이 결과를 바탕으로 단위 시간 후의 온도를 예측해봅니다. EUE가 제일 중요하게 수행해야할 부분입니다. 데이터에 대해 선형회귀 분석을 진행합니다. 이 결과를 바탕으로 단위 시간 후의 온도를 예측해봅니다.
각 데이터들 마다 그 크기가 다양해, 크기가 클 수록 결과에 많은 영향을 미칩니다. 이에 따라 **_Z 점수 정규화_**를 진행하겠습니다.
- [정규화](<https://en.wikipedia.org/wiki/Normalization_(statistics)>)
- [z 점수 (표준 점수)](https://ko.wikipedia.org/wiki/%ED%91%9C%EC%A4%80_%EC%A0%90%EC%88%98)
예측 결과는 표준 점수로 나올 것이며, 해당 점수에 실내 온도의 표준편차를 곱하고, 평균을 더해 줌으로써 예측한 온도 값을 구할 수 있습니다.
$$z ={x - m} \over { \theta }$$ -> $$x = z * \theta + m$$
## Input Data ## Input Data
...@@ -90,3 +111,39 @@ EUE가 제일 중요하게 수행해야할 부분입니다. 데이터에 대해 ...@@ -90,3 +111,39 @@ EUE가 제일 중요하게 수행해야할 부분입니다. 데이터에 대해
[Linear Regression](https://ko.wikipedia.org/wiki/선형_회귀)를 통해서 데이터들의 선형 관계를 파악 후 다음의 온도를 예측해보려 합니다. [Linear Regression](https://ko.wikipedia.org/wiki/선형_회귀)를 통해서 데이터들의 선형 관계를 파악 후 다음의 온도를 예측해보려 합니다.
매일 자정(Day K) 데이터 처리 과정이 진행 됩니다. 따라서 (Day K - 1)의 데이터들과 (Day K - 1)까지 사용된 가중치 데이터들을 이용해 Linear Regression을 진행합니다. 데이터 처리 과정이 진행된 후의 가중치들은 (Day K)의 가중치 파일로 생성되어 저장됩니다. 매일 자정(Day K) 데이터 처리 과정이 진행 됩니다. 따라서 (Day K - 1)의 데이터들과 (Day K - 1)까지 사용된 가중치 데이터들을 이용해 Linear Regression을 진행합니다. 데이터 처리 과정이 진행된 후의 가중치들은 (Day K)의 가중치 파일로 생성되어 저장됩니다.
## Data Processing Files
데이터 처리에 관한 부분은 파이썬 코드로 진행 됩니다.
server
∟ src
∟ ...
∟ data_processing
∟ linear_regression.py
∟ main.py
∟ preprocessing.py
1. 매일 자정이 되면 서버는 child process를 생성해 **/src/data_processing/main.py** 를 호출합니다. <br><br>
2. main.py는 DB에 관한 정보를 넘겨받아, data들이 존재하는 링크를 획득합니다. <br><br>
3. 링크들을 **/src/data_processing/preprocessing.py**의 preprocessing 메소드로 넘겨줍니다. <br><br>
4. preprocessing 메소드는 수집된 데이터들과 이전까지 진행한 변수들의 정보를 연산 가능한 상태로 가공하여 반환합니다. <br><br>
- 가공 후의 데이터 타입 및 Shape
| 변수 명 | 의미 | Shape |
| :---:|:---:|:---:|
|train_x|정규화된 수집 데이터 | (n , 1)|
|train_t| 정규화된 온도 값|(n, 1)|
|weights| 가중치|(10, 1) or None|
|bias |편향|float or None|
|mean |각 데이터 범주의 평균| (10, 1)|
|std_d |각 데이터 범주의 표준 편차| (10, 1)|
<br><br>
Preprocessing 과정에서 구해진 평균과 표준 오차는 사용자의 링크 하위에 **prediction_parameters.csv**로 저장합니다.
<br><br>
5. 가공된 데이터들을 바탕으로 학습률이 0.05이며, 비용 함수는 평균제곱 오차(MSE)인 선형회귀 분석을 진행합니다.<br><br>
6. 선형 회귀 분석이 후 생긴 가중치와 편향을 **analysis_parameters.csv**로 저장합니다.<br><br>
'''
# 선형 회귀 분석
- EUE에서 사용하는 데이터에 맞추어진 Linear Regression Class 입니다.
- 기존에 진행한 가중치 값이 있는지 확인합니다.
- 존재하지 않는 다면, 가중치를 초기화 합니다.
- 초기화 된 가중치와 함께 linear regression을 진행합니다.
'''
import numpy as np
class LinearRegression:
def __init__(self, train_x, train_t, weights, bias, delta=1e-4, learning_rate=0.05, err_rate=0.01):
self.train_x = train_x.T # (n, 10) -> (10, n)
self.train_t = train_t.T # (n, 01) -> (01, n)
if weights == None or bias == None:
# Initialize Parameters - w : (1, 10), b : float
self.weights, self.bias = self.initialize(self.train_x)
else:
self.weights = weights.T # (10, 1) -> (1, 10)
self.bias = bias
self.delta = delta
self.learning_rate = learning_rate
self.err_rate = err_rate
def initialize(self, x):
'''
### 가중치 및 편향 초기화 함수
- Weight : (1, m) 꼴의 행렬
- Bias : 실수
'''
weights = np.random.random((1, x.shape[0]))
bias = np.random.random()
return weights, bias
def predict(self, x, w, b):
'''
### 예측값 계산 함수
- y_hat = x * w + b
- (1, n) = (1, 10) * (10, n) + (1, n)
'''
y_predict = np.dot(w, x) + b
return y_predict
def cost_MAE(self, x, y, w, b):
'''
### 비용 함수
- MAE (Mean Square Error) : 1/n * sigma|y_i - y_hat_i|
'''
y_predict = self.predict(x, w, b)
n = y_predict.shape[1]
mae = np.sum(np.abs(y - y_predict)) / n
return mae
def cost_MSE(self, x, y, w, b):
'''
### 비용 함수 _ MAE
- MSE (Mean Square Error) : 1/n * sigma(y_i - y_hat_i)^2
'''
y_predict = self.predict(x, w, b)
n = y_predict.shape[1]
mse = np.sum((y - y_predict)**2) / n
return mse
def gradient(self, x, y, delta, w, b):
'''
### 미분 함수
- 가중치와 편향에 대한 편미분 값 반환
'''
loss_w_delta_plus = self.cost_MSE(x, y, w + delta, b)
loss_w_delta_minus = self.cost_MSE(x, y, w - delta, b)
w_grad = (loss_w_delta_plus - loss_w_delta_minus) / (2*delta)
loss_b_delta_plus = self.cost_MSE(x, y, w, b+delta)
loss_b_delta_minus = self.cost_MSE(x, y, w, b-delta)
b_grad = np.sum(loss_b_delta_plus - loss_b_delta_minus) / (2*delta)
return w_grad, b_grad
def gradientDescent(self):
iteration = 0
w = self.weights
b = self.bias
while iteration <= 3000:
grad_w, grad_b = self.gradient(
self.train_x, self.train_t, self.delta, w, b)
loss = self.cost_MSE(self.train_x, self.train_t, w, b)
if iteration % 100 == 0:
print(iteration, " iters - cost :", loss)
print("Gradients - W :", grad_w, ", b : ", grad_b)
print("W : ", w)
print("b : ", b)
print("\n")
if loss <= self.err_rate:
print("At iter NO.{0} stop the process.\nCost : {1}".format(
iteration, loss))
break
w = w - (self.learning_rate * grad_w)
b = b - (self.learning_rate * grad_b)
iteration += 1
self.weights = w
self.bias = b
if __name__ == "__main__":
print("This is test set.")
x = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6],
[5, 6, 7], [6, 7, 8]], dtype=float)
y = np.array([[2], [3], [4], [5], [6], [7]], dtype=float)
test_model = LinearRegression(
x, y, None, None, learning_rate=0.0005)
print("X : ", test_model.train_x)
print("T : ", test_model.train_t, " Shape : ", test_model.train_t.shape)
print("W : ", test_model.weights)
print("b : ", test_model.bias)
print("delta : ", test_model.delta)
print("learning rate : ", test_model.learning_rate)
print("Error Rate : ", test_model.err_rate)
test_model.gradientDescent()
print("After L.R.____")
print("* Costs *\n", test_model.cost_MSE(test_model.train_x,
test_model.train_t, test_model.weights, test_model.bias))
print("* Weights *\n", test_model.weights)
print("* Bias *\n", test_model.bias)
...@@ -5,30 +5,48 @@ ...@@ -5,30 +5,48 @@
- 진행된 후의 Weights를 파일로 저장합니다. - 진행된 후의 Weights를 파일로 저장합니다.
""" """
import datetime
from os import getcwd
import sys import sys
import pymysql import pymysql
import numpy as np
from preprocessing import preprocessingData from preprocessing import preprocessingData
from linear_regression import LinearRegression
def getUsersDataLinks(dbconfig): def storeParameters(link, filename, data):
eue_db = pymysql.connect(user=dbconfig["user"], password=dbconfig["password"], today = datetime.datetime.today()
host=dbconfig["host"], db=dbconfig["database"], charset='utf8') year = str(today.year)
cursor = eue_db.cursor(pymysql.cursors.DictCursor) month = str(today.month) if today.month >= 10 else '0'+str(today.month)
day = str(today.day) if today.day >= 10 else '0'+str(today.day)
query = "SELECT ID,DATALINK FROM USER;" time_dir = '/' + year + '/' + year+month + '/' + year + month + day
cursor.execute(query)
result = cursor.fetchall()
return result file_dir = getcwd() + '/server' + link + time_dir + filename
file = open(file_dir, "w")
file.write(data)
file.close()
dbconfig = {"host": sys.argv[1], "user": sys.argv[2], dbconfig = {"host": sys.argv[1], "user": sys.argv[2],
"password": sys.argv[3], "database": sys.argv[4]} "password": sys.argv[3], "database": sys.argv[4]}
eue_db = pymysql.connect(user=dbconfig["user"], password=dbconfig["password"],
host=dbconfig["host"], db=dbconfig["database"], charset='utf8')
cursor = eue_db.cursor(pymysql.cursors.DictCursor)
query = "SELECT ID,DATALINK FROM USER;"
cursor.execute(query)
result = cursor.fetchall()
for userdata in result:
users = getUsersDataLinks(dbconfig) print("User ID : ", userdata["ID"])
print("Data Processing Start...")
for userdata in users:
# Get Data links # Get Data links
# ./data/DO/SGG/EMD/Users/ID # ./data/DO/SGG/EMD/Users/ID
user_datalink = userdata["DATALINK"] user_datalink = userdata["DATALINK"]
...@@ -37,7 +55,65 @@ for userdata in users: ...@@ -37,7 +55,65 @@ for userdata in users:
outside_datalink = ("/").join(dir_ls[:-2]) + "/Outside" outside_datalink = ("/").join(dir_ls[:-2]) + "/Outside"
# data load # data load
train_x, train_t = preprocessingData(user_datalink, outside_datalink) train_x, train_t, weights, bias, mean, std_d = preprocessingData(
user_datalink, outside_datalink)
# linear regression # linear regression
pass model = LinearRegression(train_x, train_t, weights,
bias, learning_rate=0.05)
model.gradientDescent()
'''
# Test Codes Start.
'''
print("After Linear Regression -\n")
test_data = np.array([[5], [20], [0], [16.87], [40], [
1011], [0.72], [26.70], [47.00], [64]])
print(test_data.shape, mean.shape, std_d.shape)
test_data = (test_data - mean) / std_d
y_hat = model.predict(test_data, model.weights, model.bias)
print(y_hat.shape)
print("Test Data.\n", test_data, "\n")
print("Predict - standard deviation : ", y_hat)
print("Predict - temperature : ", y_hat*std_d[7][0] + mean[7][0], "\n")
print("Cost.")
print(model.cost_MSE(model.train_x, model.train_t,
model.weights, model.bias), "\n")
print("Weights.")
print(model.weights, "\n")
print("Bias.")
print(model.bias)
'''
# Test Codes End.
'''
# Save the Parameters.
# - analysis_parameters
analysis_data = ""
for i in range(len(model.weights[0])):
analysis_data += str(model.weights[0][i]) + ','
analysis_data += str(model.bias)
storeParameters(user_datalink, "/analysis_parameters.csv", analysis_data)
# - prediction_parameters
prediction_data = ""
for i in range(len(mean)):
prediction_data += str(mean[i][0]) + ','
prediction_data = prediction_data[:-1]
prediction_data += '\n'
for i in range(len(std_d)):
prediction_data += str(std_d[i][0]) + ','
prediction_data = prediction_data[:-1]
storeParameters(
user_datalink, "/prediction_parameters.csv", prediction_data)
...@@ -10,10 +10,9 @@ import csv ...@@ -10,10 +10,9 @@ import csv
import numpy as np import numpy as np
def loadRawData(link): def loadRawData(link, file_name):
''' '''
# CSV 파일의 내용을 반환하는 함수 ### CSV 파일의 내용을 반환하는 함수
- 어제 하루 기록된 파일들에 대해 진행하기 위해 날짜 정보를 생성합니다.
- 제공 받은 링크를 통해 파일을 읽고 반환합니다. - 제공 받은 링크를 통해 파일을 읽고 반환합니다.
''' '''
raw_data = [] raw_data = []
...@@ -28,9 +27,14 @@ def loadRawData(link): ...@@ -28,9 +27,14 @@ def loadRawData(link):
str(yesterday.year) + str(yMonth) + "/" + \ str(yesterday.year) + str(yMonth) + "/" + \
str(yesterday.year) + str(yMonth) + str(yDay) str(yesterday.year) + str(yMonth) + str(yDay)
weather_dir = os.getcwd() + "/server" + link + time_dir + "/weather.csv" file_dir = os.getcwd() + "/server" + link + time_dir + file_name
data_file = open(weather_dir, 'r', newline='') if not os.path.isfile(file_dir):
print("File doesn't exist on {0}".format(file_dir))
return None
data_file = open(file_dir, 'r', newline='')
print("Data File before CSV reader.\n", data_file)
csv_data = csv.reader(data_file) csv_data = csv.reader(data_file)
for line in csv_data: for line in csv_data:
...@@ -109,6 +113,22 @@ def handleOutRawData(out_data): ...@@ -109,6 +113,22 @@ def handleOutRawData(out_data):
return out_dict return out_dict
def handleParameters(raw_w):
if raw_w == None:
return None, None
weights = []
for line in raw_w:
for fig in line:
weights.append([float(fig)])
bias = weights.pop()[0]
return weights, bias
def combineXdata(user_x, out_dict): def combineXdata(user_x, out_dict):
''' '''
# 분리된 입력 데이터를 합치는 함수 # 분리된 입력 데이터를 합치는 함수
...@@ -118,30 +138,104 @@ def combineXdata(user_x, out_dict): ...@@ -118,30 +138,104 @@ def combineXdata(user_x, out_dict):
for line in user_x: for line in user_x:
hour, temp, humi, lights = line hour, temp, humi, lights = line
x = out_dict[hour] + [temp, humi, lights]
# 데이터 수집이 균일하게 이루어지지 않은 경우 처리
if hour in out_dict:
key_hour = hour
else:
minimum = 4
key_hour = None
for h in range(hour-3, hour + 3):
if h in out_dict and abs(h - hour) < minimum:
minimum = abs(h-hour)
key_hour = h
x = out_dict[key_hour] + [temp, humi, lights]
train_x.append(x) train_x.append(x)
return train_x return train_x
def Xnormalize(data):
'''
### 정규화 함수
- 입력 층의 데이터를 정규화 시킵니다.
'''
normalized_data = data.T # (n,10) -> (10,n)
mean = np.mean(normalized_data, axis=1) # 평균 (10, 1)
std_d = np.std(normalized_data, axis=1) # 표준편차
# 월, 일의 평균과 표준편차 지정
new_mean = []
for i, fig in enumerate(list(mean)):
if i == 0:
new_mean.append(6.5)
elif i == 1:
new_mean.append(16.0)
else:
new_mean.append(fig)
new_mean = np.array(new_mean).reshape((-1, 1))
new_std_d = []
for i, fig in enumerate(list(std_d)):
if i == 0:
new_std_d.append(3.45205253)
elif i == 1:
new_std_d.append(8.94427191)
else:
new_std_d.append(fig)
new_std_d = np.array(new_std_d).reshape((-1, 1))
normalized_data = (normalized_data - new_mean) / new_std_d
normalized_data = normalized_data.T
return normalized_data, new_mean, new_std_d
def normalize(data):
n_data = data.T # (n,10) -> (10,n)
mean = np.mean(n_data, axis=1) # 평균
std_d = np.std(n_data, axis=1) # 표준편차
n_data = (n_data - mean) / std_d
n_data = n_data.T
return n_data
def preprocessingData(user_link, out_link): def preprocessingData(user_link, out_link):
''' '''
# 데이터 분석 전 데이터 전처리 함수입니다. # 데이터 분석 전 데이터 전처리 함수입니다.
1. 데이터 로드 1. 데이터 로드
2. 데이터 1차 가공 (handle~RawData) 2. 데이터 1차 가공 (handle~RawData)
3. 데이터 2차 가공 (combineXdata) 3. 데이터 2차 가공 (combineXdata)
4. 데이터 3차 가공 (nomalize~)
4. 데이터 넘파이 형식 배열로 변환 4. 데이터 넘파이 형식 배열로 변환
5. 반환 5. 반환
''' '''
raw_user_data = loadRawData(user_link) raw_user_data = loadRawData(user_link, "/weather.csv")
raw_out_data = loadRawData(out_link) raw_out_data = loadRawData(out_link, "/weather.csv")
raw_parameters = loadRawData(user_link, "/parameters.csv")
user_x, train_t = handleUserRawData(raw_user_data) user_x, train_t = handleUserRawData(raw_user_data)
out_dict = handleOutRawData(raw_out_data) out_dict = handleOutRawData(raw_out_data)
weights, bias = handleParameters(raw_parameters)
train_x = combineXdata(user_x, out_dict) train_x = combineXdata(user_x, out_dict)
train_x = np.array(train_x) train_x = np.array(train_x) # (n ,10)
train_t = np.array(train_t) train_x, mean, std_d = Xnormalize(train_x)
train_t = np.array(train_t) # (10,1)
train_t = normalize(train_t)
weights = np.array(weights) if weights != None else None
bias = float(bias) if bias != None else None
return train_x, train_t return train_x, train_t, weights, bias, mean, std_d
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment