반응형


+ const와 pointer 헛갈림 주의!
pointer(*) vs const pointer( *const )
포인터냐 콘스트 포인터냐?

주소를 보호하는 걸까 데이터를 보호하는 걸까? 
const뒤에 오는 것이 중요! *p면 값 보호, p면 주소 보호.
또는 영어로 코드를 거꾸로 읽으면 간단하다.


1)  값의 보호 ; const 뒤에 *가 있다.   (많이 사용. 값의 보호가 주로 목적)

  • 그냥 포인터임. p is a pointer. p앞에 *가 있다.
const char *p =&xxx;          ====> const 뒤에 *가 있으면 값의 보호다.
char const *p = &xxx ;  (상동!) ==> const 뒤에 *가 있으면 값의 보호다.

변수 p 바로 앞에 *가 있으면 그냥 일반 포인터가 된다. (const pointer가 아니라 일반 포인터일뿐) 
포인터가 가리키는 타입이 const char ; 값 보호.
p is a pointer to  const char/char const(same) ; 코드를 거꾸로 읽으면 이렇게 됨.
*p=1;            // error!!  const로 지정된 값 보호.  값 변경 불가.
p=&yy ;          // ok!  주소가 변경됨.


2) 주소 보호 ; const 뒤에 *가 없음. 앞에 있음. (많이 쓰이지 않음. 선언과 동시에 초기화 필요.)

  • 콘스트 포인터임. const pointer​  (*const). 포인터 보호.
int *const p = &xxx ;     
int *const p ;    ==> 에러! 초기화를 해줘야 한다. 왜? 변경불가이기 때문에...

변수 p 바로 앞에 *가 없으면 앞을 묶어서 타입으로 봐야 한다. *const 이므로 const pointer 가 된다. (일반 포인터가 아니다.)
p is a const pointer(*) to int. ; 코드를 거꾸로 읽으면 이렇게 됨.

*p=1;            // ok 값 변경.
p=&yy ;          // error! 주소변경 불가.


3)  값과 주소 둘 다 보호
const int *const p=&xxx;
p is a const pointer(*) to const int. 
*p = 1 ;     // error
p = &yy;     // error


즉, *가 어디에(변수에? or const에?)  붙었나 살펴보거나, 코드를 뒤에서 부터 읽으면 된다.



반응형



++ Linear Regression with multi-variables
X의 feature들이 여러 개 x1, x2, ...

import tensorflow as tf
# y = x1*2+x2+x3 training
# W => 2,1,1, b=0
x_train = [[1,2,3],[2,3,4],[3,4,5],[4,5,6], [1,3,5]]
y_train = [[7],[11],[15],[19], [10]]

#placeholder
x = tf.placeholder(tf.float32, shape=[None,3])
y = tf.placeholder(tf.float32, shape=[None,1])
# variables
W = tf.Variable(tf.random_normal(shape=[3,1]), name='W')
b = tf.Variable(tf.random_normal(shape=[1]), name='b')

# model
hypothesis = tf.matmul(x, W) + b
cost = tf.reduce_mean( tf.square(hypothesis-y) )
# train
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train = optimizer.minimize(cost)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# test
# hres= sess.run(hypothesis, feed_dict={x:x_train, y:y_train})
for i in range(3001):
    _, pcost, _W, _b= sess.run([train, cost, W, b], feed_dict={x:x_train, y:y_train})
    if i%500==0:
        print (i, pcost, _W, _b)

# test
print( sess.run(hypothesis, feed_dict={x: [[4, 2, 3]]}))





반응형



1. Linear Regression 

++ single attribute . 

H(x) = x*W + b
cost(W,b) = 1/m * 오차제곱의 합  =   오차제곱의 평균. (편차제곱의 평균은 분산이다.)
   = 1/m * Sigma(  (H(x)-y)^2  )                    # cost함수를 여기에다가 1/2을 곱하여 사용하기도 한다. 그 때의 미분결과는 아래에 2*가 없어진다.
dJ/dW = 2* (1/m) * Sigma(  (H(x)-y) x )
#train
W := W - alpha* dJ/dW

x_train=[1,2,3]
y_train=[1,2,3]

W=tf.Variable(tf.random_normal([1]), name='weight')
b = tf.Variable(tf.random_normal([1]), name="bias')
hypothesis = x_train * W + b

cost = tf.reduce_mean(  tf.square(hypothesis - y_train) )

optimizer = tf.train.GradientDescentOptimizer( learning_rate=0.1 )
train = optimizer.minimize(cost)

sess = tf.Session()
sess.run( tf.global_variables_initializer())
for step in range(2001):
     sess.run(train)
     if step%100==0:
          print(step, sess.run(cost), sess.run(W), sess.run(b) )

+ 예측 
print ( sess.run( hypothesis , {X:[100]} ) )



반응형




-학습데이터 저장 및 복구

: 저장
변수들 선언. (tf.Variables....) 주의! 이름을 지정.
W1 = tf.Variable( tf.truncated_normal(shape=[INPUTSIZE, HIEEDNSIZE]), dtype=tf.float32, name='W1')
저장할 변수들 지정

param_list={ 'W1':W1, 'b1':b1, 'W2':W2, 'b2':b2}
saver = tf.train.Saver( param_list )
...
saver.save(sess, './savedata.ckpt', write_meta_graph=False)     #디렉터리 명시

: 로딩
변수들 선언. (tf.Variables....) 주의! 이름을 지정. (저장시 사용했던 variables 그대로 복사)
saver 초기화도 동일
param_list={ 'W1':W1, 'b1':b1, 'W2':W2, 'b2':b2}
saver = tf.train.Saver( param_list )
...
sess=tf.Session()
saver.restore(sess, './savedata.ckpt')
로딩 완료. W1, b1, ... 변수들 사용 가능.



반응형


+ 자료 처리 및 많이 사용하는 함수들...

-Shape, Rank, Axis
t=tf.constant(  [1,2,3,4])
tf.shape(t).eval()
     tensor의 shape과 타입을 알수 있다.   Rank는 처음에 [의 개수로 볼 수 있음.
     array ( [4],  dtype=int32 )

t=tf.constant(  [[1,2],  [3,4] ])
tf.shape(t).eval()
     array ( [2,2],  dtype=int32 )

     축에도 번호를 매길수 있는데, 가장큰 범위부터 0으로 매김.
     2차원배열의 경우 0은 행방향, 1은 열 방향.

-Matrix 곱

tf.matmul( matrix1, matrix2)          ; Matrix 곱; 내적
matrix1*matrix2     ; 성분곱.
 ( *과 matmul은 다름. 주의!)

;Broadcasting  알아서 형을 변환하여 연산해 줌. (편하지만 주의할 필요가 있음)



-reduce_sum( input_tensor, axis=None)

axis가 없으면 총합. 축은 큰 범위에서부터 인덱스가 0임.

입력이 1차원이면 축은 의미없음. axis=0이 됨.
입력이 2차원이면
axis=0 세로방향으로 합.  (테이블 input이 있으면, 아래에 답을 쓴 것)
axis=1 가로방향으로 합. (테이블 input에서 오른쪽에 답을 단 것)
axis=-1 이면 가장 마지막 축. 2차원에서는 1이됨. 3차원에서는 2가 됨.
axis가 없으면 성분들 총합.


-reduce_mean( tensor, axis )
평균
tf.reduce_mean(x, axis=0)

-argmax  ; 최대값의 인덱스
tf.argmax(x, axis=1)

-reshape ; 텐서 재구성
t=np.array( [[[0,1,2], [3,4,5]],    [[6,7,8],[9,10,11]] ] )
tf.reshape(t, shape=[-1,3])  ; -1은 알아서 다른 성분크기에 맞게 자동조정.
[[0,1,2], [3,4,5], [6,7,8], [9,10,11]]

비슷한 함수. squeeze, expand

-onehot encoding
t=tf.one_hot(  [[0], [1], [2], [0]],  depth=3)
[ [[1, 0, 0]] , [[0,1,0]], [[0,0,1]], [[1,0,0]] ]          #주의 rank가 올라감!!!
원래의 차수로 내리려면
tf.reshape ( t, [-1, 3] )
[ [1,0,0], [0,1,0], [0,0,1], [1,0,0] ]


-타입 캐스팅
tf.cast( [1.8, 2.2], tf.int32)
tf.cast(  [True, False, 1==1, 1==0], tf.int32 )
     [1, 0, 1, 0]

-스택
x=[1,2], y=[3,4], z=[5,6]
np.stack( [x,y,z] )
          =>   [[1,2], [3,4], [5,6]]
np.stack( [x,y,z], axis=1)
          =>  [[1, 3, 5], [2,4,6]]

-ones and zeros like
tf.ones_like(x).eval()          # .eval()은 값과 타입을 출력해준다.
x의 shape과 같은데 값을 모두 1로 채움.
tf.zeros_like(x)

-Zip ; 묶어준다.
for x, y, z in zip( [1,2,3], [4,5,6], [7,8,9] ):
     print (x, y, z)   
1 4 7 
2 5 8
3 6 9
zip을 하지 않고 출력하면?
for x, y, z in ( [1,2,3], [4,5,6], [7,8,9] ):          # 또는 [[1,2,3],[4,5,6],[7,8,9]]
     print (x, y, z)   
1 2 3
4 5 6
7 8 9



반응형



+자료형

1. PlaceHolder
텐서를 저장. (핸들값). 바로 계산되지는 않는다.
input data 저장시. feed dictionary=맵핑시켜주는 역할. (입력값들로 그래프 실행시 입력할 수 있다.)

tf.placeholder(dtype, shape=None, name=None)
     데이터 타입(dtype);     tf.float32, tf....

     p1 = tf.placeholder(tf.float32, shape=(3,3))
     feeding을 해주어야 한다.

# place holder test
ph1 = tf.placeholder(tf.float32)
ph2 = tf.placeholder(tf.float32)
ph3 = tf.placeholder(tf.float32)

value1=3
value2=4
value3=5

feed_dict = {ph1:value1, ph2:value2, ph3:value3}

ph4 = ph1+ph2*ph3

result=s1.run(ph4, feed_dict)
#or  result = s1.run(ph4, {ph1:value1, ph2:value2, ph3:[2.3]})
print(result)



2. Variable (대문자V 주의!)
     weight를 저장시 사용. (그래프 계산시에 내부에서 변경되는 값들. 초기화가 필요.)
v1 = tf.Variable([1,2,3,4], dtype=tf.float32)
v2 = tf.Variable([1,2,3,4], dtype=tf.float32)
v3=v1*v2
print(v3) ; 역시 출력되지 않는다.
sess.run(v3) ; 에러 발생!
원인은 variable은 반드시 초기화가 필요하다. (weight 초기화 같이)
sess.run 전에 반드시 초기화를 돌려주어야한다. (예외, 저장된 vars restore의 경우는 안해도 됨.)
init = tf.global_variables_initializer()
sess.run(init)
또는
     sess.run( tf.global_variables_initializer())

이후부터 sess.run(v3)하면 계산이 된다.

초기화시킨 variables

weights = tf.Variable( tf.random_normal([784,200], stddev=0.35), name="weights")
또는
weights = tf.Variable( tf.truncated_normal( [None, 200] ) )

biases = tf.Variable(tf.zeros([200]), name="biases")

-변수의 값 변경assign()으로 한다.
gradient = tf.reduce_mean( (W*X-Y)*X)
descent = W-0.1*gradient
update = W.assign(descent)
sess.run(update)



3. constant
tf.zeros(shape, dtype=tf.float32, name=None)
tf.zeros_like(tensor, dtype=None, name=None, optimizer=True)
tf.ones(...)
tf.constant(value, dtype=None, shape=None, ..)

c1 = tf.zeros([3,4], tf.int32)


위 값들을 직접 print하면 객체 정보만 나오고 실제 값을 알 수 없음.
세션을 만들고 실행해 줘야 함.


4. Session   세션.
연산 그래프 묶음을 의미.
세션.run() . 세션단위로 실행. (그래프 실행)

import tensorflow as tf
hello = tf.constant('Hello, TensorFlow!')
sess = tf.Session()
print( sess.run(hello))

세션에 입력되는 텐서는 그래프 말단 노드로 보면 된다. 앞에 있는 것을 따라서 다 실행됨.
run시에 텐서 맵핑 테이블 추가하여  placeholder와 값을 맵핑시킨다.
run의 결과로 받으면 데이터를 로딩 및 출력이 가능하다. Weight, bias 정보를 얻을 수 있다.

result = sess.run(hello)
w = sess.run(w)
b = sess.run(b)
print(result)


tensor_map={x:input_x, y_:output_y}
_,tmp_cost,acc = sess.run( [train, cost, accuracy], tensor_map)
출력이 필요없는 것은 _로 받으면 된다.


다른 출력 방법??? eval() 이용
print ("Accuracy:", accuracy.eval( session=sess, feed_dict={x:inputx, y:outputy}) )

단,  sess = InteractiveSession() 으로 디폴트 세션을 열어주어야 한다.


마지막에 세션 close를 위해서 with as 구문 사용
with tf.Session() as sess:
     sess.run(train)
자동으로 위 블록탈출시 sess.close() 됨.




반응형



+TensorFlow

machine learning 오픈소스 라이브러리. python 기반.
계산 그래프(computational graph) 를 생성하여 텐서가 흐르는 프로그램


+ 로딩
import tensorflow as tf

로딩이 안되면 tensorflow를 설치한다.



+버전 확인
tf.__version__
'1.1.0'


+텐서 (Tensor)
Rank ; 차원
여기서는 모든 자료형이 텐서다. 원래는 정적타입의 n차원 배열 or list ; 랭크값이 차원수. 1차원은 벡터, 2차원은 매트릭스, 3차원부터 텐서다.
rank 0 ; scalar 1
rank 1 ; vector [1,2,3]
rank 2 ; matrix [[1,2],[3,4]]
rank 3 ; 3-tensor [ [[1],[2]], [[3],[4]] ]
rank n ; n-tensor

Shape ; dimension number. 
rank 1 ;  shape [4]
rank 2 ;  shape [4,2]  ; 4x2 행렬
rank 3 ;  shape [3,4,5]    ; 3x4x5 행렬

DataTypes
tf.float32     ; 대부분 함수에서 디폴트 자료형임.
tf.float64
tf.int8, 16, 32, 64
tf.uint8, 16
tf.string
tf.bool
tf.complex64, 128



+ 기본 예제, 작동 확인:   hello world -> hello tensorflow

import tensorflow as tf
hello = tf.constant('Hello tensorflow!')
sess = tf.Session()
print ( sess.run(hello) )
-------------
b'Hello tensorflow!'
위와 같이 출력됨.
b는 bytes를 의미. 


------------------------------------------------------------------
+ 간단한 더하기 계산그래프 테스트

3+4를 계산하는 그래프.

import tensorflow as tf
# build graph(tensor)
node1=tf.constant(3.0, tf.float32)
node2=tf.constant(4.0)
node3 = tf.add(node1, node2)
# 위 값을 print("node1=",node1, "node2=",node2, "node3=",node3)로 출력해 봐야 주소와 타입만 찍힌다. 값을 모름.
# feed data and run graph, update vars and return.
sess = tf.Session()
print ( sess.run( [node1, node2] ) )          # node1, node2를 구하여 출력.
print ( sess.run( [node3] ) )     # node3인 계산 결과를 출력. (윗줄은 데이터 값을 확인하기 위한 디버깅용)
sess.close()



반응형


+LIBCURL 라이브러리로 POST data 전송하기 또는 curl 커맨드로 전송하기

https도 가능함.


#include <curl/curl.h>

#include <syslog.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>


#define CURLCMD "curl"


struct PostResult {

size_t size;

char* ptr;

};



void init_string(struct PostResult *s)

{

s->size = 0;

s->ptr = malloc(s->size + 1);

if(s->ptr == NULL) {

fprintf(stderr," malloc() fail\n");

exit(EXIT_FAILURE);

}

s->ptr[0] = 0;

}


#ifdef _CURL_LIB_

static size_t

WriteCallback(void* ptr, size_t size, size_t nmemb, struct PostResult *s)

{

size_t new_len = s->size + size * nmemb;

s->ptr = realloc(s->ptr, new_len + 1);

if(s->ptr == NULL) {

fprintf(stderr, "ralloc fail\n");

exit(EXIT_FAILURE);

}

memcpy(s->ptr + s->size, ptr, size*nmemb);

s->ptr[new_len] = 0;

s->size = new_len;

return size*nmemb;

}

#endif


int Post_Send(char* url, char* jsonMsg)

{

#ifdef _CURL_LIB_

int i=0;

CURL *curl=NULL;

CURLcode res;

#endif

char inmsg[1024]={0,};

struct PostResult repost;

int maxsize=0 ;


// cmdline method

#ifdef _CURL_CMD_

char inmsg2[1024]={0,};

char cmdline[4096]={0,};

char result[1024]={0,};

#endif


if(!url || !jsonMsg) {

return -1;

}


init_string(&repost);


memset(inmsg, 0, sizeof(inmsg));

maxsize = strlen(jsonMsg)>sizeof(inmsg) ? sizeof(inmsg) : strlen(jsonMsg) ;

memcpy(inmsg, jsonMsg, maxsize) ;


// CURL 라이브러리 방식

#ifdef _CURL_LIB_

curl = curl_easy_init();

if(curl)

{

const int timeout = 30000;

i = strlen(inmsg);

curl_easy_setopt(curl, CURLOPT_URL, url);

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, inmsg);

curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(inmsg));

curl_easy_setopt(curl, CURLOPT_POST, 1L);

curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout/1000);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, &repost);


res = curl_easy_perform(curl);

if(CURLE_OK != res)

{

// server error

return 1;

}


if(repost.size > 1){

// 수신 데이터 주소 : repost.ptr

curl_easy_cleanup(curl);

return -1;

}else{

printf("error: %s\n", strerror(res));

curl_easy_cleanup(curl);

// server error

            return 1;

}

curl_easy_cleanup(curl);

}

#endif


// CURL 커맨드 방식

#ifdef _CURL_CMD_

{

int contimeout=10 ;  // secs

FILE *fp=NULL ;

int index=0 ;

int rbytes=0 ;


memset(inmsg2, 0, sizeof(inmsg2)) ;

q2dq(inmsg, inmsg2, sizeof(inmsg2)) ;    // " -> \"로 변경하는 함수

snprintf(cmdline, sizeof(cmdline)-1, "%s --connect-timeout %d -s -d \"%s\" -k \"%s\"",

  CURLCMD, contimeout, inmsg2, url) ;


fp = popen(cmdline, "r") ;

if ( fp==NULL ) {

// server error

}

else {

do {

rbytes=fread(result+index, 1, sizeof(result)-index-1, fp) ;

#ifdef _DEBUG

printf("rbytees=%d\n", rbytes) ;

#endif

if ( rbytes<=0 )

break; 

index+=rbytes ;

} while(rbytes!=0 );

pclose(fp) ;


#ifdef _DEBUG

printf("rcved=%s\n", result) ;

#endif

if( strlen(result)>1 ){

// 수신 데이터 주소: result

} else {

strcpy(tqResult->result, "100") ; // server error

}

#ifdef _DEBUG

printf("success post request\n");

#endif

}

}

#endif


return 0;

}



일부 함수는 없지만 적절히 수정하면 사용할 수 있다.


예를 들어 보내는 데이터를 "submit=1" 이렇게 하면 POST 수신쪽에서는 php의 경우 $_POST["submit"] 으로 받을 수 있다. 

form data가 아닌 raw data를 그대로 받으려면 

$post_raw_data = file_get_contents("php://input") ;

이렇게 한다.


다른 예제)

https://curl.haxx.se/libcurl/c/post-callback.html




반응형

+if or 비교시 어떤 식의 성공으로 진입했는지 구분

가끔 복수의 or 조건으로 진입한 경우, 어떤 식의 성공으로 왔는지 간단하게 구분이 필요할 수 있다.

다시 어떤 식인지 판단해줘야 하는데 귀찮은 작업이다.

어떤 식의 만족으로 먼저 들어왔는지 간단히 판단하려면... 다음과 같은 팁이 있다.


예를 들어, 입력값 조건 순서가 

1. 길이가 3이상이거나 

2. a로 시작하거나 

3. z로 끝난다.

위 세 조건을 or로 하여 먼저 만족하는 것은 어떤 것인가를 판단.


string str="....." ;

int ret=0 ;

if (  (ret=1, str.length()>=3 ) ||

    (ret=2, str.at(0)=='a') ||

   (ret=3, str.at( str.length()-1)=='z') ) {

std::cout << " match.  ret=" << ret << std::endl ;

 } else std::cout << " no match. " << std::endl ;


결과는 다음과 같다.

str="12345"  인 경우  ret=1  (길이 조건)

str="ab" 인 경우 ret=2 (a로 시작)

str="kz" 인 경우 ret=3 (z로 끝)

str="abz" 인 경우 ret=1 (길이 조건, a로 시작, z로 끝.  앞의 조건부터 판단하므로 ret=1로 됨.)







'Develop > C&CPP' 카테고리의 다른 글

const pointer or pointer / int *const / int const * / const int *  (0) 2018.07.19
libcurl HTTP POST send 모듈/curl 커맨드 방식도 지원  (0) 2018.07.13
Numerics library  (0) 2018.06.21
Preprocessor  (0) 2018.06.20
deque  (0) 2018.06.13
반응형


+mysql에서 쿼리 결과를 변수로 저장하여 사용하기


변수는 앞에 @을 붙인다.
변수에 값을 할당시 set, select로 할 수 있다. 할당시에는 := 로 한다. 

SET @user:=123456;
select @group:=group from TUSER where user=@user;
select * from user where group=@group;



+ Recent posts