반응형

올바른 분류 모델을 학습시키기 위해 데이터셋을 골고루 분할하는 것이 중요하다. 

 

https://github.com/ewine-project/UWB-LOS-NLOS-Data-Set

 

GitHub - ewine-project/UWB-LOS-NLOS-Data-Set: Repository with UWB data traces representing LOS and NLOS channel conditions in 7

Repository with UWB data traces representing LOS and NLOS channel conditions in 7 different indoor locations. - GitHub - ewine-project/UWB-LOS-NLOS-Data-Set: Repository with UWB data traces represe...

github.com

 

예를 위해 위 Github에서 0과 1로 이루이진 이진 클래스 데이터 셋이 있다. 이 글은 데이터를 라벨에 맞게 골고루 분리하는 것이므로 데이터 분석은 따로 하지 않는다. 

 

csv 파일은 7개이며, 총 데이터의 개수는 42000개이다.  

sklearn 라이브러리에서 train_test_split을 사용하면 간단히 데이터를 분할할 수 있다. 아래 코드에서 간단히 데이터셋을 불러올 수 있다. 이 데이터셋의 경우 nlos가 클래스(혹은 정답 데이터)이다. 아래의 그림을 보게 되면 0, 1, 0, 1, 1...로 무작위로 정렬돼었다. 각 클래스의 개수를 출력하면, 21000개를 확인할 수 있다.

import uwb_dataset
import pandas as pd


columns, data = uwb_dataset.import_from_files()

for item in data:
	item[15:] = item[15:]/float(item[2])

print("\nColumns :", columns.shape, sep=" ")
print("Data :", data.shape, sep=" ")
print(type(data))

df_uwb = pd.DataFrame(data=data, columns=columns)
print(df_uwb.head(10))

los_count = df_uwb.query("NLOS == 0")["NLOS"].count()
nlos_count = df_uwb.query("NLOS == 1")["NLOS"].count()

print("Line of Sight Count :", los_count)
print("Non Line of Sight Count :", nlos_count)

"""
결과
./dataset/uwb_dataset_part5.csv
./dataset/uwb_dataset_part7.csv
./dataset/uwb_dataset_part2.csv
./dataset/uwb_dataset_part3.csv
./dataset/uwb_dataset_part4.csv
./dataset/uwb_dataset_part1.csv
./dataset/uwb_dataset_part6.csv

Columns : (1031,)
Data : (42000, 1031)
<class 'numpy.ndarray'>

Line of Sight Count : 21000
Non Line of Sight Count : 21000
"""

 

결과

파이썬으로 개발을 하면서 느낀 것은 최대한 반복문을 지양하고 라이브러리를 사용하는 것이다. 파이썬은 빠르게 데모 프로그램 구현에 많이 사용하는데 라이브러리가 이를 가능케 한다. 그리고 가장 큰 이유는 내가 만든 코드는 절대 라이브러리를 이길 수 없다는 것이다.  이번에 사용하고자 하는 train_test_split은 sklearn 라이브러리의 함수이다. sklearn는 머신러닝 대표 라이브러리이지만 딥러닝 사용에 있어 문제가 없다.   

 

train_test_split : 배열 또는 행렬을 무작위 학습 및 테스트 하위 집합으로 분할.

 

 -test_size : 0~1 사이의 값으로, 기본 test size는 0.25로 자동으로 train size는 0.75이다. 아래의 그림처럼 데이터를 분할.

- random_state : shuffle 제어하는 인자이다. 모델의 성능을 향상시키기 위해 다양한 방법으로 모델을 디자인한다. 하지만 공정한 검증을 위해 똑같은 데이터셋을 필요로 한다. 그 때 사용하는 인자이다. 

- shuffle : 분리하기 전에 데이터를 섞을지 여부. 

- stratify : 가장 중요한 파라미터. 클래스에 맞게 골고루 분할할지 여부. 

from sklearn.model_selection import train_test_split


x_train, x_test, y_train, y_test = train_test_split(
    df_uwb[["CIR"+str(i) for i in range(cir_n)]].values,
    df_uwb['NLOS'].values,
    test_size=0.2,
    random_state=42,
    shuffle=True,
    stratify=df_uwb['NLOS'].values)
    
print("x_train shape :", x_train.shape, y_train.shape)
print("x_test shape :", x_test.shape, y_test.shape)

print("Train NLOS 0 count :", len(y_train[y_train==0]))
print("Train NLOS 1 count :", len(y_train[y_train==1]))
print("Test NLOS 0 count :", len(y_test[y_test==0]))
print("Test NLOS 0 count :", len(y_test[y_test==1]))

"""
x_train shape : (33600, 1016) (33600,)
x_test shape : (8400, 1016) (8400,)

Train NLOS 0 count : 16800
Train NLOS 1 count : 16800
Test NLOS 0 count : 4200
Test NLOS 0 count : 4200
"""

728x90
반응형
반응형

안녕하세요. 

 

요즘 LoRa에서 End Device에서 바이트형식으로 오는 데이터를 파싱하기 위해 bytearray로 골머리를 썩고 있는데, 연구실 형님이 Python Struct을 추천해서 알게 되었습니다.

 

Python이 굉장히 잘 만든 언어이지만, 바이트나 비트를 처리하기에는 너무 까다롭습니다. 

 

bytearray를 이용해 데이터를 파싱하거나 checksum 계산을 수행할 때 PTSD가 왔는데, Python Struct는 정말 신세계에 가까웠습니다.

checksum
bytearray

 


파이썬 Struct는 C언어 Struct와 비슷합니다. 자세한 내용은 공식문서를 통해 참고하시면 됩니다.

https://docs.python.org/3/library/struct.html

 

struct — Interpret bytes as packed binary data — Python 3.9.7 documentation

struct — Interpret bytes as packed binary data Source code: Lib/struct.py This module performs conversions between Python values and C structs represented as Python bytes objects. This can be used in handling binary data stored in files or from network c

docs.python.org

 

https://coding-yoon.tistory.com/120

 

[C] UNION 공용체와 Struct 구조체를 이용해 간단한 패킷 만들기

안녕하세요. 오늘은 UNION과 STRUCT에 대해 이야기 하겠습니다. coding-yoon.tistory.com/119 [C] 구조체 포인터 접근과 최적화 요즘 기본기가 중요함을 느끼고 C를 공부하고 있습니다. 1. 구조체 단순히접근

coding-yoon.tistory.com

 

위 내용을 이해할 수 있다면, 저 말이 무슨 말인지 쉽게 이해할 수 있습니다. 

 

아래와 같은 하나의 14바이트의 packet을 전송했다고 가정합니다. ( 아래 코드는 실제 패킷 중 하나이다. 쉬운 이해를 위해 그림으로)

위 union을 설명하는 블로그에서는 __attribute__에 대해 이야기하지 않았습니다. __attribute__는 패딩 비트가 생기지 않도록 합니다. 그러므로 16바이트가 아닌 14바이트로 메모리가 할당됩니다. 

Packet

파이썬에서 위 같은 바이트로 이루어진 패킷을 받을려면 어떻게 해야하나? bytearray를 쓰려고 하면 정신이 혼미해지지만,  Python Struct를 사용하면 머리의 두통이 사라진다.

 

사용법은 간단하다. 한 줄이면 위 데이터를 쉽게 파싱할 수 있다.

 

from struct import *

"""
Do Something
"""

data = "14바이트패킷" # stirng 아님 # <class 'bytes'>

payload = unpack('<Hfff',data)

u_cnt = payload[0]
lat = payload[1]
long_ = payload[2]
alt = payload[3]

unpack 명령어 한 줄로 파싱이 가능하다.

 

'<Hfff' 의 foramt 형식만 사용할 줄 알면 된다. 간단하다. 위 python 공식 문서에 나와 있는 내용이다. 

 

1. 맨 처음쓰는 것은 바이트 정렬이다. 위 사진의 패킷은 litte endian이므로 '<' 를 추가한다. 

byteorder

2. 바이트 정렬을 적었다면, 데이터의 타입이 나오게 된다. 패킷의 구성은 unsigned int(2), float(4), float(4), float(4)의 순서로 아래 표의 C Type을 보고 해당하는 format을 적으면된다.  'HFF'

결과적으로 unpack은 list 형태로 payload를 반환하게 된다. 

 

 

728x90
반응형
반응형

안녕하세요. 

 

Low Pass Filter, High Pass Filter, Band Pass Filter를 이용한 신호 처리와 FFT 변환으로 주파수 영역에서 필터가 제대로 동작했는지 확인하는 것까지 파이썬으로 구현합니다. 


from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
import scipy.io
import os


mat_file = scipy.io.loadmat('signal1.mat')
(file_path, file_id) = os.path.split('signal1.mat')  # file path, file name

fs = 1024  # sample rate
order = 10  # order
cut_off_freq = 150  # cut off frequency

# raw signal
# t = np.linspace(0, 1, fs, False)  # 1 second
# sig = np.sin(2*np.pi*100*t) + np.sin(2*np.pi*50*t)  # signal
sig = mat_file[file_id[:-4]][0]

freq = np.fft.fftfreq(len(sig), 1/1024)

# filtered signal
sos = signal.butter(order, [cut_off_freq], 'low', fs=fs, output='sos')  # low pass filter
filtered = signal.sosfilt(sos, sig)

# raw signal fft
raw_fft = np.fft.fft(sig) / len(sig)
raw_fft_abs = abs(raw_fft)

# filter signal fft
filtered_fft = np.fft.fft(filtered) / len(filtered)
filtered_fft_abs = abs(filtered_fft)

# plot
fig, ((ax00, ax01), (ax10, ax11)) = plt.subplots(2, 2)

# raw signal plot : 0 row 0 column
ax00.plot(t, sig)
ax00.set_title('Raw Data Time Domain')
ax00.set_xlabel('Time [seconds]')
ax00.set_ylabel('Amplitude')

# filtered signal plot : 1 row 0 column
ax10.plot(t, filtered)
ax10.set_title('Filtered Data Time Domain')
ax10.set_xlabel('Time [seconds]')
ax10.set_ylabel('Amplitude')

# raw signal fft plot : 0 row 1 column
ax01.stem(freq, raw_fft_abs, use_line_collection=True)
ax01.set_title('Raw Data Frequency Domain')
ax01.set_xlabel('Frequency [HZ]')
ax01.set_ylabel('Amplitude')

# filtered signal fft plot : 1 row column
ax11.stem(freq,filtered_fft_abs, use_line_collection=True)
ax11.set_title('Filtered Data Frequency Domain')
ax11.set_xlabel('Frequency [HZ]')
ax11.set_ylabel('Amplitude')

# plot
plt.tight_layout()
plt.show()

 

 

1. Low Pass Filter

sos = signal.butter(order, [cut_off_freq], 'low', fs=fs, output='sos')
filtered = signal.sosfilt(sos, sig)

2. High Pass Filter

sos = signal.butter(order, [cut_off_freq], 'high', fs=fs, output='sos')
filtered = signal.sosfilt(sos, sig)

3. Band Pass Filter

sos = signal.butter(order, [150, 200], 'band', fs=fs, output='sos')
filtered = signal.sosfilt(sos, sig)

 


Low Pass Filter, Cut off frequency: 150Hz

 


High Pass Filter, Cut off frequency: 150Hz


Band Pass Filter, Cut off frequency: 150-200Hz

728x90
반응형
반응형

안녕하세요. 아두이노 MQ Series PPM으로 변환하기 번외 편입니다. 

 

저번 글은 회로도를 보았고, 오늘은 파이썬으로 PPM으로 변환하도록 하겠습니다.

 

파이썬으로 굳이 사용한 이유는 급하게 실험하느라, 센서 값을 PPM으로 변환하지 않고 그대로 CSV파일 형식으로 받았기 때문에 파이썬으로 데이터를 전처리해야만 했습니다.

 

import csv
import numpy as np
import math
import matplotlib.pyplot as plt

"""
PPM 
VCC = 3.3V
RL = 10k

VL = VCC*(RL/(RS+RL)
RS = (RL*VCC)/VL-RL

PPM = a * ratio * b
"""

vcc = 3.3
rl = 10
mq3, mq4, mq6, mq7, mq8, mg811 = 7, 8, 9, 10, 11, 12


#  Calculate Rs 
def rs_cal(vl):
    return ((vcc * rl) / vl) - rl


# Calculate Ro
def ro_cal(rs, num, clean_air_ppm):
    ro_tmp = 0
    for i in range(num):
        ro_tmp += rs[i] / clean_air_ppm
    return ro_tmp/num


# Calculate ratio 
def ratio_cal(rs_, ro_):
    return rs_/ro_


# Calculate PPM 
def ppm_cal(ratio, a, b):
    return a * pow(ratio, b)

# Calculate logscale PPM
def ppm_log_cal(ratio, a, b):
    return (math.log10(ratio)-b)/a


def co2_cal(adc_v):
    return pow(10, ((adc_v / 8.5) - 0.220) / (0.020 / (2.602 - 3)) + 2.602)


constant = {"mq3": ['Alcohol', "mq3", 0.3934, -1.504],
            "mq4": ['CH4', "mq4", 1012.7, -2.786],
            "mq6": ['LPG', "mq6", 1009.2, -2.35],
            "mq7": ['CO', "mq7", 99.042, -1.518],
            "mq8": ['H2', "mq8", 976.97, -0.688]}


file_name_1 = '2020923_105132.csv'
file_name_2 = '2020923_113418.csv'
file_name_3 = '2020923_125810.csv'

header = ['boot_ms[ms]',
          'latitude[degE7]', 'longitude[degE7]', 'relative altitude[mm]',
          'local position x[m]', 'local position y[m]', 'local position z[m]',
          'mq3', 'mq4', 'mq6', 'mq7', 'mq8', 'mq811',
          'PM1.0', 'PM2.5', 'PM10.0', 'ozone', 'gamma']


csv_1 = np.loadtxt(file_name_1, delimiter=",")
# file = np.vstack([header, csv_1])

adc_v_list = []
rs_list = []
ratio_list = []
ppm_list = []

tmp = []

for i in range(len(csv_1)):
    adc_v_list.append(csv_1[i][mq4])

for i in range(len(csv_1)):
    rs_list.append(rs_cal(csv_1[i][mq4]))

ro = ro_cal(rs=rs_list, num=10, clean_air_ppm=4.4)

for i in range(len(csv_1)):
    ratio_list.append(ratio_cal(rs_list[i], ro))

for i in range(len(csv_1)):
    ppm_list.append(ppm_cal(ratio_list[i], constant['mq4'][2], constant['mq4'][3]))

time = []

for i in range(len(csv_1)):
    time.append((csv_1[i][0]-csv_1[0][0])/1000/60)

print("time :", time)
print("adc_v :", adc_v_list)
print("ro :", ro)
print("rs :", rs_list)
print("ratio : ", ratio_list)
print("ppm :", ppm_list)
print("clean air :", 1012.7 * pow(4.4, -2.786))

plt.plot(time, [300 for _ in range(len(csv_1))], color='red')
# plt.plot(time, [10000 for _ in range(len(csv_1))], color='red')
plt.plot(time, ppm_list, color='green')
plt.xlabel('[Minute]')
plt.ylabel('[PPM]')
plt.title("MQ4 - CH4( 300~10000ppm )")
plt.show()

 

위 소스코드 같은 경우는 프로젝트에서 중요하다고 생각한 부분만 가져왔습니다. 

 

아래는 PPM으로 변환할 때 필요한 함수입니다.

#  Calculate Rs 
def rs_cal(vl):
    return ((vcc * rl) / vl) - rl


# Calculate Ro
def ro_cal(rs, num, clean_air_ppm):
    ro_tmp = 0
    for i in range(num):
        ro_tmp += rs[i] / clean_air_ppm
    return ro_tmp/num


# Calculate ratio 
def ratio_cal(rs_, ro_):
    return rs_/ro_


# Calculate PPM 
def ppm_cal(ratio, a, b):
    return a * pow(ratio, b)

# Calculate logscale PPM
def ppm_log_cal(ratio, a, b):
    return (math.log10(ratio)-b)/a

 

그리고 기억은 잘나지 않지만, CO2 센서는 위 공식 말고 다른 식을 사용합니다. 

# Calculate CO2 PPM
def co2_cal(adc_v):
    return pow(10, ((adc_v / 8.5) - 0.220) / (0.020 / (2.602 - 3)) + 2.602)

 

1편

coding-yoon.tistory.com/98

 

[아두이노] MQ 시리즈 공기질 센서 PPM으로 변환하기! (1) Feat. MQ2, MQ3, MQ4, MQ5, MQ6, MQ7, MQ8, MQ9, MG-811

안녕하세요. 약 두 달만에 글을 씁니다. 공모전과 기사 시험의 지옥을 뒤로 잠시 여유가 생겨 시간을 냅니다. 오늘은 MQ 시리즈에서 공기질 센서를 PPM으로 변환하는 방법에 대해 글을 쓰겠습니

coding-yoon.tistory.com

 

2편

coding-yoon.tistory.com/121

 

[아두이노] MQ 시리즈 공기질 센서 PPM으로 변환하기! (2) 회로도 (Schematic)

안녕하세요. MQ시리즈 두 번째 글을 작성합니다. 확실히 글은 바로 바로 작성하는 것이 중요한 것 같습니다. 글을 쓰려고 보니 기억이 안 나서 다시 새로 공부했습니다. 저번 글은 아두이노 라이

coding-yoon.tistory.com

 

728x90
반응형
반응형

안녕하세요. 

 

이번에 개발환경을 VSCode로 완전히 옮겼습니다.

 

첫 번째 이유는 Pylance의 등장입니다. 

coding-yoon.tistory.com/113?category=898799

두 번째 이유는 Jupyterlab입니다. 

 

VSCode 에서 간단한 환경 설정으로 .py, .ipynb 를 한번에 개발할 수 있습니다.

 

window 
python -m pip install jupyterlab

code.visualstudio.com/docs/python/jupyter-support

 

Working with Jupyter Notebooks in Visual Studio Code

Working with Jupyter Notebooks in Visual Studio Code

code.visualstudio.com

이제 확장명에 맞춰 파일을 만들면 됩니다.

 

 

파일 확장명을 .ipynb로 작성해주면 알아서 주피터 노트북으로 켜집니다. 

 

자동완성
MarkUP
파이썬 버전

 

 

 

 

anaconda를 깔지 않고도 jupyter notebook을 사용할 수 있으며, python은 

자신이 선택한 파이썬의 버전으로 생성됩니다. 

 

Pycharm은 이런 기능이 Pro로 유료버전이기 때문에, 무료로 이 정도로 편리함을 사용할 수 있다는 것에 너무 충격이였습니다. 

 

여러분들도 자신에게 맞는 개발환경을 그 때 그 때 찾으시길 바랍니다. 

728x90
반응형

'VSCode' 카테고리의 다른 글

[VScode] Visual Studio Code Theme 추천  (0) 2021.02.25
[VSCode] VSCode JAVA 세팅.  (0) 2021.01.18
[VSCode] Python Pylance 자동완성  (0) 2021.01.09
[VSCode] Python pylint  (0) 2020.12.08
[VSCode] Python 모듈 자동완성 (IntelliSense)  (0) 2020.12.08

+ Recent posts