'Math' 카테고리의 다른 글
integral ln gamma (0) | 2019.08.01 |
---|---|
integral ln sin (0) | 2019.08.01 |
적분 순서 치환방법 정리 (0) | 2019.05.05 |
미분 곡률 테일러시리즈 (0) | 2019.05.05 |
삼각함수 미적분 정리 (0) | 2019.05.05 |
integral ln gamma (0) | 2019.08.01 |
---|---|
integral ln sin (0) | 2019.08.01 |
적분 순서 치환방법 정리 (0) | 2019.05.05 |
미분 곡률 테일러시리즈 (0) | 2019.05.05 |
삼각함수 미적분 정리 (0) | 2019.05.05 |
keras 손실함수 중에 아래 두 개가 비슷하지만 사용할 때는 완전히 다르다.
주의가 필요하다.
+ categorical_crossentropy ; 다중 분류 손실함수. one-hot encoding 클래스
출력값이 one-hot encoding 된 결과로 나오고 실측 결과와의 비교시에도 실측 결과는 one-hot encoding 형태로 구성된다.
예를 들면 출력 실측값이 아래와 같은 형태(one-hot encoding)로 만들어 줘야 하는 과정을 거쳐야 한다.
[[0 0 1]
[0 1 0]
[1 0 0]] (배치 사이즈 3개인 경우)
네트웍 레이어 구성시 마지막에 Dense(3, activation='softmax') 로 3개의 클래스 각각 별로 positive 확률값이 나오게 된다.
[0.2, 0.3, 0.5]
위 네트웍 출력값과 실측값의 오차값을 계산한다.
model.compile(optimizer=.., loss='categorical_entropy')
+ sparse_categorical_crossentropy ; 다중 분류 손실함수. 위와 동일하지만 , integer type 클래스라는 것이 다르다.
예를 들면 출력 실측값이 아래와 같은 형태로 one-hot encoding 과정을 하지 않아도 된다.
[0, 1, 2] (배치 사이즈 3개로 했을 때)
네트웍 구성은 동일하게 Dense(3, activation='softmax')로 하고 출력값도 3개가 나오게 된다.
단 실측 출력값을 입력하는 부분에서 별도로 one-hot encoding을 할 필요가 없이 정수값 그대로 주고, 손실함수를 sparse_categorical_crossentropy 로 바꿔주기만 하면 된다.
model.compile(optimizer=.., loss='sparse_categorical_entropy')
타이타닉 kaggle 자료 분석 (0) | 2019.08.23 |
---|---|
Jupyter Lab/ TensorBoard 원격접속/방화벽 (1) | 2019.08.09 |
워드벡터를 사용하여 기사분류하기1 (0) | 2019.04.15 |
나무위키 데이터베이스 워드벡터(word2vec) 만들기 (2) | 2019.04.12 |
SVM 간단 예제 (0) | 2018.09.04 |
벡터 구조체 필드 기준으로 최대값 최소값 찾기
#include <algorithm>
#include <vector>
typedef struct _A {
double x ;
double y ;
} A ;
bool compareA(const A& a1, const A&a2) {
// 앞에 있는 노드의 x값이 더 작게 소팅한다.
return a1.x < a2.x ;
}
std::vector<A> alist ;
A tmp ;
tmp.x = 10 ;
tmp.y = 70 ;
alist.push_back(tmp) ;
tmp.x = 5 ;
tmp.y = 60 ;
alist.push_back(tmp) ;
tmp.x = 3 ;
tmp.y = 50 ;
alist.push_back(tmp) ;
tmp.x = 8 ;
tmp.y = 80 ;
alist.push_back(tmp) ;
A mina = *std::min_element(alist.begin(), alist.end(), compareA) ;
A maxa = *std::max_element(alist.begin(), alist.end(), compareA) ;
// 이터레이터를 리턴하므로 *를 붙여 객체값을 얻어온다.
printf("mina %lf %lf \n", mina.x, mina.y) ;
printf("maxa %lf %lf \n", maxa.x, maxa.y) ;
[알고리즘] 정렬1: selection sort (0) | 2019.12.13 |
---|---|
ASN.1c (0) | 2019.08.01 |
smart pointer 스마트포인터? (0) | 2018.07.19 |
const pointer or pointer / int *const / int const * / const int * (0) | 2018.07.19 |
libcurl HTTP POST send 모듈/curl 커맨드 방식도 지원 (0) | 2018.07.13 |
[UI] Qt5
파이썬으로 간단한 UI 프로그램 개발
QWidget , inputBox, MessageBox, 버튼 처리. 텍스트 출력. 도형 그리기.
슬라이드바 사용.
옛날에는 윈도우에서 VS로 MFC나 C# windows form 등을 만들었었는데, 좀 더 쉽게 간단하게 만들 방법이 없을까 하다가. 리눅스에서 Python으로 PyQt5를 한 번 써보게 됐다.
먼저 PyQt5를 설치해 준다. Qt는 어느 플랫폼에서도 돌아가니까 좋은 것 같다.
만들 프로그램은 조건에 따른 통계 수치를 기록하는 간단한 구조이다.
먼저 분석할 데이터를 DB에서 가져와 numpy save file로 만들어 두었다.
아래 프로그램에서는 save data를 로딩해서 분석만 하면 된다.
조건에 따른 분기를 순서도 처럼 그린다.
도형 그림을 그려야 되기 때문에 도형 클래스를 간단하게 만든다.
도형은 네모, 다이아(조건) 두 개로 하고, 선분 클래스도 추가한다.
네모 타입은 내부에 텍스트를 출력한다.
다이아 타입도 내부에 텍스트 출력 기능이 있고, 왼쪽, 오른쪽에 각각 텍스트 출력도 한다.
필요한 라이브로리 로딩.
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
SHAPE_RECT = 0
SHAPE_DIA = 1
class ShapeObject():
def __init__(self, x,y,w,h, shape, name):
self.rect = QRectF(x,y,w,h) # x,y w,h
self.x = x
self.y = y
self.w = w
self.h = h
self.shape = shape
self.name = name
self.text = name
self.text_l = ''
self.text_r = ''
self.value=0.0
self.button=None
def set_name(self, n):
self.name = n
self.text = self.name+'\n'+str(self.value)
def set_text(self, t, addName=False):
if addName:
self.text = self.name+'\n'+t
else:
self.text = t
def set_value(self, v):
self.value = v
self.text = self.name+'\n'+str(v)
def set_textl(self, l):
self.text_l = l
def set_textr(self, r):
self.text_r = r
def set_button(self, btn):
self.button = btn
def draw(self, painter):
if self.shape == SHAPE_RECT:
painter.drawRect(self.rect) # x,y, w,h
painter.drawText(self.rect, Qt.AlignCenter, self.text)
elif self.shape == SHAPE_DIA:
points = [QPoint(self.rect.center().x(), self.rect.top()),
QPoint(self.rect.right(), self.rect.center().y()),
QPoint(self.rect.center().x(), self.rect.bottom()),
QPoint(self.rect.left(), self.rect.center().y())]
painter.drawPolygon(QPolygon(points))
painter.drawText(self.rect, Qt.AlignCenter, self.text)
if len(self.text_l)>0:
rect = QRectF( self.x-50, self.y+10, 50, 50 )
painter.drawText(rect, Qt.AlignCenter, self.text_l)
if len(self.text_r)>0:
rect = QRectF( self.x+self.w+10, self.y+10, 50, 50 )
painter.drawText(rect, Qt.AlignCenter, self.text_r)
도형들을 이어주는 선분의 위치 정보 얻는 함수
align은 C면 첫번째 도형의 가운데, L=left, R=right에서 선이 출발하도록 한다.
def get_connect_line(o1, o2, align='C'):
points=[0,0,0,0, 0]
if align=='C':
points[0]=int(o1.x+o1.w/2)
points[1]=int(o1.y+o1.h)
elif align=='L':
points[0]=int(o1.x)
points[1]=int(o1.y+o1.h/2)
points[4]=0x0000FF
elif align=='R':
points[0]=int(o1.x+o1.w)
points[1]=int(o1.y+o1.h/2)
points[4]=0xFF0000
points[2]=int(o2.x+o2.w/2)
points[3]=int(o2.y)
return points
앱의 메인이다. 좌표들은 그림을 먼저 그림판에다 대충 그리고, 좌표를 대략적으로 뽑아서 출력해 본다.
class MyApp(QWidget):
def __init__(self):
super().__init__()
self.shapes = []
self.lines = []
self.selected = 0
self.slideValue = 0.0
self.statmsg = ''
self.statmsg1 = ''
self.statmsg2 = ''
self.initUI()
def initUI(self):
self.setWindowTitle('Decision Graph')
self.setWindowIcon(QIcon('icon1.png'))# 메인 화면 크기 위치 지정.
self.move(300,300)
self.resize(650,800)
############## 버튼. 클릭 이벤트 콜백 설정. 종료연결.
btnQuit = QPushButton('Quit', self)
btnQuit.setToolTip('exit <b>decision graph</b> program')
btnQuit.move(10, 10)
btnQuit.resize( btnQuit.sizeHint())
btnQuit.clicked.connect(QCoreApplication.instance().quit)
offx=20
## 네모 도형 객체를 만든다.
self.shape1 = ShapeObject(offx+200, 50, 200, 50, SHAPE_RECT, 'CompareSet')
self.shapes.append(self.shape1)
## 아래쪽에 다이아 객체를 만든다.
self.shape2 = ShapeObject(offx+200, 150, 200, 50, SHAPE_DIA, 'v2.0')
self.shape2.set_text('0.9', True)
self.shape2.set_value(0.9)
self.shape2.set_textl('869')
self.shape2.set_textr('3584')
self.shapes.append(self.shape2)
## 선분 객체를 만든다. 네모와 다이아를 연결한다.
self.lines.append( get_connect_line(self.shape1, self.shape2, 'C'))
## 왼쪽 아래에 다이아 객체 추가.
self.shape3 = ShapeObject(offx+100, 240, 200, 50, SHAPE_DIA, 'P0')
self.shape3.set_text('0.7', True)
self.shape3.set_value(0.7)
self.shape3.set_textl('744')
self.shape3.set_textr('125')
self.shapes.append(self.shape3)
self.lines.append( get_connect_line(self.shape2, self.shape3, 'L'))## 버튼을 추가. user-defined callback으로 설정. 클릭 이벤트 처리.
self.btnShape3 = QPushButton('M', self)
self.btnShape3.move(self.shape3.x, self.shape3.y)
self.btnShape3.resize(self.btnShape3.sizeHint())
self.btnShape3.clicked.connect(self.btnShape3Click)
## 이런식으로 순서도 도형들을 그리고, 텍스트 정보 등을 추가한다.
self.shape4 = ShapeObject(offx+420, 240, 50, 50, SHAPE_RECT, 'F')
self.shapes.append(self.shape4)
self.lines.append( get_connect_line(self.shape2, self.shape4, 'R'))
self.shape5 = ShapeObject(offx+20, 340, 200, 50, SHAPE_DIA, 'P8')
self.shape5.set_text('0.8', True)
self.shape5.set_value(0.8)
self.shape5.set_textl('608')
self.shape5.set_textr('136')
self.shapes.append(self.shape5)
self.lines.append( get_connect_line(self.shape3, self.shape5, 'L'))
self.btnShape5 = QPushButton('A', self)
self.btnShape5.move(self.shape5.x, self.shape5.y)
self.btnShape5.resize(self.btnShape5.sizeHint())
self.btnShape5.clicked.connect(self.btnShape5Click)
self.shape6 = ShapeObject(offx+350, 340, 200, 50, SHAPE_DIA, 'P7')
self.shape6.set_text('0.6', True)
self.shape6.set_value(0.6)
self.shape6.set_textl('80')
self.shape6.set_textr('45')
self.shapes.append(self.shape6)
self.lines.append( get_connect_line(self.shape3, self.shape6, 'R'))
self.btnShape6 = QPushButton('B', self)
self.btnShape6.move(self.shape6.x, self.shape6.y)
self.btnShape6.resize(self.btnShape6.sizeHint())
self.btnShape6.clicked.connect(self.btnShape6Click)
self.shape7 = ShapeObject(offx+10, 470, 50, 50, SHAPE_RECT, 'T')
self.shapes.append(self.shape7)
self.lines.append( get_connect_line(self.shape5, self.shape7, 'L'))
self.shape8 = ShapeObject(offx+200, 470, 50, 50, SHAPE_RECT, 'F')
self.shapes.append(self.shape8)
self.lines.append( get_connect_line(self.shape5, self.shape8, 'R'))
self.shape9 = ShapeObject(offx+300, 470, 50, 50, SHAPE_RECT, 'T')
self.shapes.append(self.shape9)
self.lines.append( get_connect_line(self.shape6, self.shape9, 'L'))
self.shape10 = ShapeObject(offx+530, 470, 50, 50, SHAPE_RECT, 'F')
self.shapes.append(self.shape10)
self.lines.append( get_connect_line(self.shape6, self.shape10, 'R'))
# 슬라이드바 추가. 값을 조절하는 기능.
self.slider = QSlider(Qt.Horizontal, self)
self.slider.move(200, 550)
self.slider.resize(200, 20)# 0~100 까지 값을 갖게 되고, 움직임은 1씩 변경되게 한다. 최초에 0값으로 설정함.
self.slider.setRange(0, 100)
self.slider.setSingleStep(1)
self.slider.setValue(0)# 슬라이드를 움직여 값이 변경되면 감지되는 콜백 연결.
self.slider.valueChanged.connect(self.sliderChange)
# 하나의 버튼이 눌리면 다른 버튼들은 gray로 하고, 눌려진 버튼이 불 들어오게 한다.
btnUpdate = QPushButton('Update', self)
btnUpdate.setToolTip('test')
btnUpdate.move(250, 580)
btnUpdate.resize( btnUpdate.sizeHint())
btnUpdate.clicked.connect(self.btnUpdateClick)
self.btnShape3.setStyleSheet("background-color:gray")
self.btnShape5.setStyleSheet("background-color:gray")
self.btnShape6.setStyleSheet("background-color:gray")
btnChange = QPushButton('Change', self)
btnChange.setToolTip('change factor')
btnChange.move(10, 600)
btnChange.resize (btnChange.sizeHint())
btnChange.clicked.connect(self.btnChangeClick)
btnInput = QPushButton('Input', self)
btnInput.setToolTip('input threshold')
btnInput.move(410, 550)
btnInput.resize(50, 20)
btnInput.clicked.connect(self.btnInputClick)
self.show()
# 버튼이 눌린쪽의 도형의 값을 슬라이드 값으로 변경한다.
def sliderChange(self, v):
# print( self.selected, v) # v 0~100
if self.selected>0:
shape = self.shapes[self.selected-1]
shape.set_value(v/self.slider.maximum())
self.slideValue = v/self.slider.maximum()
updatestat(self) ## live check... slow...
self.update()
def nextCaptureName(self, head):
for i in range(1000):
filename = head+"{:03d}".format(i)+".png"
if not os.path.exists(filename):
break
return filename
# 현재 윈도우 화면을 캡쳐해 봤다. 0으로 하면 전체 화면이 캡쳐된다. 맥에서 해보니 항상 전체화면이 캡쳐되었다. 버전이 다르긴 함.
def take_screenshot(self):
# full screen capture
# self.preview_screen = QApplication.primaryScreen().grabWindow(0)
self.preview_screen = QApplication.primaryScreen().grabWindow(self.winId())
filename = self.nextCaptureName("signanalyze_graph_")
print('filename=', filename)
self.preview_screen.save(filename)
def btnUpdateClick(self):
updatestat(self)
self.update()
self.take_screenshot()
# 슬라이드 말고 직접 값을 입력할 때, 입력 받도록 하였다.
def btnInputClick(self):
if self.selected>0:
text, okpressed = QInputDialog.getText(self, "Input", "Input Value(0.0~1.0):", QLineEdit.Normal, "" )
if okpressed and text!='':
try:
v = float(text)
self.slider.setValue(v*100)
except:
QMessageBox.about(self, "Input", "Invalid value!")
def btnChangeClick(self):
if self.selected>0:
text, okpressed = QInputDialog.getText(self, "Input", "Input Facotr(P0~P8):", QLineEdit.Normal, "" )
text = text.upper()
if okpressed and text in ['P0', 'P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8']:
shape = self.shapes[self.selected-1]
shape.set_name(text)
updatestat(self)
self.update()
elif text=="" :
pass
else:
QMessageBox.about(self, "Input", "Invalid P factor name!")
# 눌려진 버튼의 색을 변경한다. 다른 버튼들은 리셋함.
def btnShape3Click(self):
self.selected = 3
self.slideValue = self.shape3.value
self.slider.setValue(self.shape3.value * self.slider.maximum())
self.btnShape3.setStyleSheet("background-color:blue")
self.btnShape5.setStyleSheet("background-color:gray")
self.btnShape6.setStyleSheet("background-color:gray")
self.update()
def btnShape5Click(self):
self.selected = 5
self.slideValue = self.shape5.value
self.slider.setValue(self.shape5.value * self.slider.maximum())
self.btnShape3.setStyleSheet("background-color:gray")
self.btnShape5.setStyleSheet("background-color:blue")
self.btnShape6.setStyleSheet("background-color:gray")
self.update()
def btnShape6Click(self):
self.selected = 6
self.slideValue = self.shape6.value
self.slider.setValue(self.shape6.value * self.slider.maximum())
self.btnShape3.setStyleSheet("background-color:gray")
self.btnShape5.setStyleSheet("background-color:gray")
self.btnShape6.setStyleSheet("background-color:blue")
self.update()
# 그림을 그린다.
def paintEvent(self, QPaintEvent):
painter = QPainter(self)
painter.setPen(QPen(Qt.black, 1))
for s in self.shapes:
s.draw(painter)
for l in self.lines:
if l[4]==0:
painter.setPen(QPen(Qt.black, 1))
else:
painter.setPen(QPen(QColor(l[4]), 1))
painter.drawLine(l[0], l[1], l[2], l[3])
painter.setPen(QPen(Qt.black, 1))
rect = QRectF(10, 530, 200, 50)
if self.selected>0:
painter.drawText(rect, Qt.AlignCenter, 'Selected : ' + self.shapes[self.selected-1].name )
else:
painter.drawText(rect, Qt.AlignCenter, 'Selected : None' )
rect = QRectF(400, 530, 200, 50)
painter.drawText(rect, Qt.AlignCenter, str(self.slideValue))
# 텍스트 출력.. align 설정.
rect = QRectF(200, 610, 500, 50)
painter.drawText(rect, Qt.AlignLeft, str(self.statmsg))
rect = QRectF(450, 50, 500, 50)
painter.drawText(rect, Qt.AlignLeft, str(self.statmsg1))
rect = QRectF(450, 150, 500, 50)
painter.drawText(rect, Qt.AlignLeft, str(self.statmsg2))
프로그램 구동
app = QApplication([])
ex = MyApp()
sys.exit(app.exec_())
Google Drive file upload/download (0) | 2019.08.20 |
---|---|
Fourier Transform Python (1) | 2019.08.02 |
두 선분의 교차여부 체크 (0) | 2019.04.11 |
두 선분의 교점 찾기 (0) | 2019.04.11 |
모든 성분에 따옴표붙여서 컴마 리스트로 출력하기 (0) | 2019.04.11 |
integral ln sin (0) | 2019.08.01 |
---|---|
Gaussian integration (0) | 2019.07.26 |
미분 곡률 테일러시리즈 (0) | 2019.05.05 |
삼각함수 미적분 정리 (0) | 2019.05.05 |
sin함수 적분 (0) | 2019.05.05 |
Gaussian integration (0) | 2019.07.26 |
---|---|
적분 순서 치환방법 정리 (0) | 2019.05.05 |
삼각함수 미적분 정리 (0) | 2019.05.05 |
sin함수 적분 (0) | 2019.05.05 |
감마 함수 (0) | 2019.05.05 |
적분 순서 치환방법 정리 (0) | 2019.05.05 |
---|---|
미분 곡률 테일러시리즈 (0) | 2019.05.05 |
sin함수 적분 (0) | 2019.05.05 |
감마 함수 (0) | 2019.05.05 |
가우스적분 (0) | 2019.05.05 |
미분 곡률 테일러시리즈 (0) | 2019.05.05 |
---|---|
삼각함수 미적분 정리 (0) | 2019.05.05 |
감마 함수 (0) | 2019.05.05 |
가우스적분 (0) | 2019.05.05 |
퓨리에시리즈. 스텝함수 (0) | 2019.05.05 |
삼각함수 미적분 정리 (0) | 2019.05.05 |
---|---|
sin함수 적분 (0) | 2019.05.05 |
가우스적분 (0) | 2019.05.05 |
퓨리에시리즈. 스텝함수 (0) | 2019.05.05 |
[이상한 수학] pi = 0? (1) | 2019.04.03 |
sin함수 적분 (0) | 2019.05.05 |
---|---|
감마 함수 (0) | 2019.05.05 |
퓨리에시리즈. 스텝함수 (0) | 2019.05.05 |
[이상한 수학] pi = 0? (1) | 2019.04.03 |
root i, 허수 i의 루트. 이게 말이 돼? (0) | 2019.04.01 |