이 게시글은 기계 학습과 기계 학습 모두에 새롭게 등장하는 독자를 위한 것입니다.


MNIST가 무엇인지 이미 알고 있다면 softmax( multinomial logistic)회귀이 무엇인지를 알 수 있으며, 이는 보다 빠른 속도의 자습서를 선호할 수 있습니다.


튜토리얼을 시작하기 전에 반드시 TensorFlow를 설치해야 합니다.


프로그래밍하는 법을 배울 때,"HelloWorld"는 "HelloWorld"를 인쇄하는 것과 같은 전통을 가지고 있습니다. 프로그래밍이 HelloWorld를 하는 것은 이번 튜토리얼과 같은 문맥입니다.


MNIST는 간단한 컴퓨터 비전 데이터 세트입니다. 이는 다음과 같이 손으로 작성한 숫자의 이미지로 구성됩니다.


또한 각 이미지에 대한 라벨이 포함되어 있으며, 각 이미지에 해당하는 숫자를 알려 줍니다.

 예를 들어 위 이미지의 레이블은 5,0,4,1입니다.


이 튜토리얼에서, 우리는 이미지를 관찰하고 그들이 어떤 숫자인지 예측할 수 있도록 모델을 훈련시킬 것입니다.

우리의 목표는 최첨단 성능을 발휘하는 정교한 모델을 훈련시키는 것이 아니라, 나중에 할 수 있도록 코드를 부여하는 것입니다!--하지만 발가락을 사용하여 발가락 부분을 찍는 것이 낫다. 

이와 같이 우리는 매우 단순한 모델로 시작할 것입니다. 바로 Softmax 회귀라는 회귀 모델입니다.


+ 즉, 나중에 훈련시킨 모델들을 가져오는 원리들을 파악 및 softmax 회귀 모델을 알아가는 부분인 것 같습니다.


이 튜토리얼의 실제 코드는 매우 짧으며, 모든 재미 있는 것들은 세줄로 되어 있습니다.하지만, 그것 이면의 아이디어들을 이해하는 것은 매우 중요하다.이것 때문에, 우리는 매우 신중하게 코드를 완성할 것입니다.


본 자습서는 mnist_softmax.py 라인 코드에서 발생하는 일련의 설명, 라인별로 설명합니다.


본 자습서는 다음을 비롯하여 몇가지 다른 방법으로 사용할 수 있습니다.

1) 각 줄의 설명을 통해 읽을 수 있는 대로 각 코드를 라인별로 구분하여 라인 업으로 복사하고 붙여 넣으십시오.

2) 설명서를 읽기 전에 전체 mnist_softmax.py Python 파일을 실행하고 이 자습서를 사용하여 명확하지 않은 코드를 이해할 수 있도록 합니다.


수행할 내용:

1)데이터 중복 제거 기술에 대한 자세한 내용 및 데이터 중복 제거 기술에 대해 알아보기.

2)이미지의 모든 픽셀을 보는 데 기반하여 자릿수를 인식하는 기능을 생성합니다.

3)TensorFlow를 사용하여 모델을 " 보기"로 인식하여 모델을 식별하고, 수천개의 예제를 실행할 수 있도록 합니다.

4)테스트 데이터를 통해 모델의 정확도를 점검하십시오.

The MNIST Data

MNIST 데이터는 Yann LeCun의 웹 사이트에서 호스팅 됩니다.

이 자습서에서 코드를 복사하고 붙여 넣는 경우, 여기서 데이터를 자동으로 다운로드하고 읽을 수 있는 코드 두줄로 시작하십시오.

from tensorflow.examples.tutorials.mnist import input_data
mnist
= input_data.read_data_sets("MNIST_data/", one_hot=True)

MNIST 데이터는 세 부분으로 나뉩니다. 즉, 교육 데이터의 55,000개의 데이터 포인트( mnist.train), 테스트 데이터의 10,000포인트( mnist.test), 검증 데이터의 5,000포인트( mnist.validation)등이 있습니다.

이 세분류는 매우 중요합니다. 우리가 배워야 할 것은 우리가 배우지 못한 것을 확실히 할 수 있는 별개의 데이터를 가지고 있다는 것입니다.


앞서 언급한 바와 같이, 모든 MNIST 데이터 포인트에는 두개의 파트가 있습니다. 즉, 손으로 작성한 숫자와 해당 라벨의 이미지입니다.

우리는 이미지"x"와 라벨"y"를 부를 것입니다. 교육 세트 및 테스트 세트에는 이미지 및 해당 라벨이 모두 포함되어 있습니다. 예를 들어 교육용 이미지는 mnist.train.images이며, 교육용 레이블은 mnist.train.labels.입니다.


각 이미지는 28픽셀 x28픽셀입니다. NAT은 다음과 같은 다양한 수치로 해석할 수 있습니다.


우리는 이 배열을 28x28의 벡터의 벡터로 평평하게 만들 수 있다. 우리가 이미지들 사이에 일관성을 유지하는 한, 우리가 어떻게 배열할지는 중요하지 않습니다.

이러한 관점에서 볼 때, MNIST 이미지는 매우 풍부한 구조(경고:시각화 집약적 시각화)를 가진 벡터 기반 벡터 공간의 수많은 포인트일 뿐입니다.


평평한 데이터에서 이미지의 2D구조에 대한 정보가 삭제됩니다. 최고의 컴퓨터 비전 방법은 이 구조를 이용하는 거죠. 그리고 우리는 나중에 튜토리얼을 쓸 것입니다. 그러나 우리가 여기서 사용할 간단한 방법은 다음과 같습니다.


결과적으로 mnist.train.images는 55000( n-dimensional, 784, ])의 텐서이다. 첫번째 차원은 영상 목록에 있는 색인이며 두번째 차원은 각 영상의 각 픽셀에 대한 인덱스입니다.텐서( tensor)의 각 항목은 특정 영상의 특정 화소에 대해 0과 1사이의 화소 강도이다.

각 그림 MNIST의 각 이미지에는 해당 이미지에 그려진 숫자를 나타내는 0~9사이의 숫자가 있습니다.


본 자습서를 위해 저희는 라벨을 "one-hot 벡터"라고 부르고자 합니다. 벡터 기반 벡터는 대부분의 차원에서 0이며, 단일 차원의 1차원이다. 이 경우 n번째 숫자는 n번째 치수의 1개의 벡터로 표현됩니다.예를 들어, 3은[0,0,0,0,0,0,0,0,0,0]입니다. 결과적으로 mnist.train.labels는[ 55000,10]kg의 부동 소수 점 배열이다.

우리는 이제 실제로 모델을 만들 준비가 됐어요!


Softmax Regressions

파이썬을 사용하여 효율적인 숫자 계산을 하기 위해서, 우리는 보통 Python곱셈기와 같은 비싼 작업을 하는 NumPy 같은 라이버리을 사용한다. 다른 언어로 구현된 매우 효율적인 코드이다.

불행히도, 모든 운영 체제로 전환하는 데는 여전히 많은 오버 헤드가 존재할 수 있습니다.

이 오버 헤드는 특히 데이터 전송에 높은 비용이 들 수 있는 분산된 방식이나 분산된 방식으로 계산하려는 경우에 특히 나쁩니다.


TensorFlow는 또한 Python을 없애기 위해 많은 노력을 하지만, 이러한 오버 헤드를 피하기 위해 한 걸음 더 나아 간다.

Python은 파이썬을 사용하여 독립적으로 운영하는 것을 대신하는 대신에 파이선을 사용하여 운영되는 상호 작용 작업의 그래프에 대해 설명합니다.(이와 같은 접근 방식은 몇개의 기계 학습 라이브러리에서 볼 수 있습니다.)


TensorFlow를 사용하려면 먼저 가져와야 합니다.

import tensorflow as tf
import tensorflow as tf

우리는 상징적 변수를 조작하여 이러한 상호 작용 운영을 설명한다. 다음을 생성합니다.

x = tf.placeholder(tf.float32, [None, 784])

x는 특정한 가치가 아니다. 이것은 자리 표시자입니다. 우리가 계산대에서 계산할 때 우리가 입력할 가치가 있는 값입니다.

우리는 각각의 MNIST 이미지들을 784-dimensional 벡터로 바꿀 수 있는 숫자를 입력할 수 있기를 원합니다.

우리는 이것을 부동 소수 점 이하의 부동 소수 점 숫자의 2차원 텐서( 784)로 표현한다. (여기서는 치수가 어떤 길이라도 될 수 있음을 의미한다.)

우리는 또한 모델에 대한 체중(Weights)과 편견(Biases)이 필요합니다. 우리는 이것들을 추가 투입하는 것을 상상할 수 있지만, TensorFlow는 그것을 다루는 더 나은 방법을 가지고 있습니다. Variable

Variable는 상호 작용의 상호 작용에 대한 TensorFlow의 그래프에서 수정 가능한 수정 가능한 텐서이다.

그것은 계산에 의해 사용되고 심지어 수정될 수도 있다. 기계 학습 애플리케이션의 경우 일반적으로 모델 매개 변수는 변수 변수가 됩니다.

W = tf.Variable(tf.zeros([784, 10]))
b
= tf.Variable(tf.zeros([10]))

우리는 변수의 초기 값을 tf.Variable의 초기 값으로 줌으로써 이 변수를 생성합니다. 이 경우에는 W과 b을 tf.zeros 0으로 나눕니다.

우리는 W와 b를 배울 것이기 때문에, 그것들이 처음에는 그다지 중요하지 않다.


W는[ 784,10]의 형태를 가지고 있습니다. 왜냐하면 우리는 벡터의 벡터 벡터를 곱하기 위해 다른 등급의 벡터 벡터를 생성하기 위해 벡터 벡터를 곱하고 싶습니다.b는 출력에 추가할 수 있도록[10]의 모양을 가지고 있다.

이제 모델을 구현할 수 있습니다. 그것을 정의하는데 한줄만 걸려요!

y = tf.nn.softmax(tf.matmul(x, W) + b)

첫째로, 우리는 x, W, W의 표현으로 x를 곱합니다.

이것은 우리가 곱셈 부호를 가지고 있는 우리의 방정식으로, 우리가 여러개의 입력을 가진 2D텐서를 다루는 작은 속임수로 우리의 방정식에 넣은 것에서 힌트를 얻었다.

그리고 나서 우리는 b를 추가하고, 마침내 tf.nn.softmax.를 적용한다.

바로 그거에요. 몇번의 짧은 설치 후에 모델을 정의할 수 있는 선이 하나밖에 없었습니다.

그것은 TensorFlow가 특별히 쉽게 회귀할 수 있도록 설계되었기 때문이 아니다.

그것은 기계 학습 모델에서부터 물리학 시뮬레이션에 이르기까지 많은 숫자의 수치 연산을 묘사하는 매우 유연한 방법입니다.

그리고 일단 정의된 대로, 우리의 모델은 컴퓨터의 CPU, GPUs, 심지어는 심지어 전화기로도 작동할 수 있습니다!

Training

모델을 훈련시키기 위해서, 우리는 모델이 좋은 것이 무엇인지를 의미하는 것을 정의해야 합니다.

실제로, 기계 학습에서는 전형적으로 모델이 나쁘다는 것을 의미합니다.

우리는 이것을 원가 혹은 손실이라 부르며, 그것은 우리의 모델이 원하는 결과로부터 얼마나 멀리 떨어져 있는지를 나타냅니다.

우리는 에러를 최소화하려고 합니다. 에러 마진이 적을수록 우리의 모델은 더 좋습니다.

모델의 분실을 결정하기 위한 매우 일반적이고 매우 훌륭한 기능은 "cross-entropy"라고 불립니다.

정보 이론은 정보 이론에서 정보 압축 코드에 대해 생각하는 것에서 기인하지만, 도박에서부터 기계 학습에 이르기까지 많은 분야에서 중요한 아이디어가 된다. 다음과 같이 정의됩니다.


여기서 y는 예측 가능한 확률 분포이며 y ′는 실제 분포(자릿수 라벨을 사용한 one-hot 벡터)이다.

대략적으로, cross-entropy는 우리의 예측이 진실을 설명하는 데 얼마나 비효율적인지를 측정하고 있다.

cross-entropy에 대한 자세한 내용은 본 자습서의 범위를 벗어나지만 이해할 만한 가치가 충분히 있습니다.


cross-entropy를 구현하려면 먼저 새 자리 표시자를 추가하여 올바른 답을 입력해야 합니다.

y_ = tf.placeholder(tf.float32, [None, 10])

우리는 cross-entropy 기능을 구현할 수 있다. ylog(y):

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

첫째, tf.log는 y의 각 요소의 대수를 계산한다. 다음으로 y-y의 원소를 곱하고 y^y(y)와 같은 원소를 곱한다.

그런 다음 tf.reduce_sum는 reduction_indices=[1 매개 변수로 인해 y의 두번째 치수에 해당하는 요소를 추가합니다.

마지막으로, tf.reduce_mean는 배치의 모든 예제에 대한 평균을 계산합니다.


소스 코드에서는 이 공식을 사용하지 않습니다. 숫자가 불안정하기 때문입니다. 그 대신에 unnormalized(x, W)+b(x, W)에 softmax_cross_entropy_with_logits를 tf.nn.softmax_cross_entropy_with_logits에 적용한다.

이는 보다 수치적으로 안정적인 기능을 통해 내부적으로 softmax 활성화를 계산합니다. 코드를 사용하는 경우 대신 tf.nn.softmax_cross_entropy_with_logits를 사용하는 것을 고려해 보십시오.


이제 우리가 원하는 것이 무엇인지 알 수 있으므로, 우리가 그것을 하기 위해 TensorFlow를 훈련시키는 것은 매우 쉬워요.

왜냐하면 TensorFlow는 당신의 계산의 전체 그래프를 알고 있기 때문입니다. 자동화 알고리즘을 사용하여 변수가 손실되는 손실에 어떻게 영향을 미치는지 효율적으로 결정할 수 있습니다.

그런 다음 최적화 알고리즘을 적용하여 변수를 수정하고 손실을 줄일 수 있습니다.

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

이 경우에, 우리는 TensorFlow에게 0.5의 학습 속도로 구배 하강 알고리즘을 사용하여 cross_entropy를 최소화할 것을 요청한다.경사 하강은 간단한 절차입니다. 여기서 TensorFlow는 단순히 각 변수를 비용을 감소시키는 방향으로 조금씩 돌립니다. 하지만 TensorFlow는 여러가지 다른 최적화 알고리즘을 제공합니다. 만약 한개만 한다면 하나의 선을 조정하는 것만큼 간단합니다.


TensorFlow가 실제로 여기서 수행하는 것은 backpropagation와 경사도 하강을 구현하는 그래프에 새로운 연산을 추가하는 것입니다. 그런 다음, 단일 작업을 수행합니다. 단, 작동 시 기울기 하강 훈련을 수행하여 변수를 약간 수정하고 손실을 줄입니다.


이제 InteractiveSession에서 모델을 시작할 수 있습니다.

sess = tf.InteractiveSession()

먼저 생성한 변수를 초기화하기 위한 작업을 생성해야 합니다.

tf.global_variables_initializer().run()

훈련을 시작합시다--훈련 스텝은 1000번입니다!

for _ in range(1000):
  batch_xs
, batch_ys = mnist.train.next_batch(100)
  sess
.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

각 단계마다 100개의 무작위 데이터 포인트가 배치되어 있습니다. 교육 세트에서 백개의 랜덤 데이터 포인트를 얻을 수 있습니다. 우리는 배치 데이터에서 자리 표시자를 대체하기 위해 train_step 데이터를 실행한다.


무작위 데이터의 소량 배치를 확률적 훈련이라 부르며 이 경우 확률적 경사 하강 하강이다. 이상적으로는, 우리는 모든 훈련 과정을 위해 모든 데이터를 사용하고 싶습니다. 왜냐하면 우리는 우리가 해야 할 일을 더 잘 이해할 수 있기 때문입니다. 하지만 그것은 비쌉니다. 따라서, 우리는 매번마다 다른 하위 집합을 사용합니다. 이것을 하는 것은 싸고 이로운 점도 많다.

Evaluating Our Model

우리의 모델은 얼마나 잘 되나요?

글쎄요, 우선 정확한 라벨을 어디에 뒀는지 알아냅시다. tf.argmax는 어떤 축을 따라 가장 높은 진입률의 지수를 나타내는 매우 유용한 기능이다. 예를 들어, tf.argmax(y, 1)은 각 입력에 대해 가장 가능성이 높은 라벨이며, tf.argmax(y_, 1)은 정확한 라벨로 표시된다. 우리는 우리의 예측이 진실과 일치하는지를 확인하기 위해 tf.equal를 사용할 수 있다.

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

그것은 우리에게 booleans 리스트를 제공한다. 정확한 비율을 결정하기 위해, 우리는 부동 소수 점 숫자를 선택한 다음 평균을 취한다. 예를 들어,[True, False, True, True]는 0.75가 될[1,0,1,1]이 됩니다.

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

마지막으로, 우리는 우리의 시험 데이타에 대한 정확성을 요구한다.

print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

이는 약 92%여야 합니다.

good ? 어떤가요? 글쎄, 그렇진 않아. 사실, 그것은 꽤나 나빠요. 이것은 우리가 매우 단순한 모델을 사용하고 있기 때문입니다.

약간의 깊이를 가지고 있으면 97%까지 갈 수 있어요. 최고의 모델들은 99.7%이상의 정확도를 달성할 수 있습니다! ( 자세한 내용은 이 결과 목록을 참조하십시오.)


중요한 것은 우리가 이 모델에서 배운 것입니다. 그럼에도 불구하고, 만약 여러분이 이러한 결과에 대해 조금 더 우울하다면, 우리가 훨씬 더 잘하는 다음 튜토리얼을 통해 더 정교한 모델을 만드는 방법을 배워 보세요!



출처 : https://www.tensorflow.org/get_started/mnist/beginners


추후 다음 튜토리얼을 하기 전에 실제 돌린 장면을 포함해서 올리도록 하겠습니다.


반응형

Windows10에서 사용자 프로필 폴더의 이름을 변경하는 방법 (C:\Users\Username)


윈도우에서 사용자들이 종종 C : \ Users의 프로필 폴더 이름을 바꾸는 방법을 묻습니다.

혹은 회사에서 사원이 바뀌었을 떄, 계정은 바꾸어서 주었지만,

실제 C드라이브 사용자 폴더에는 기존 사용자의 이름이 적혀있는 경우가 있습니다.


How to rename the user account profile folder in Windows 10

이 방법은 Windows10(윈도우 10):홈, Pro또는 EnterpriseEdition과 연동되지만 시스템에 손상을 입힐 수 있습니다.

따라서, 이 방법을 시도하기 전에 전체 시스템 백업을 생성해야 합니다.


제가 해본 경험상... 바로가기 파일들 빼고는 정상작동 되었습니다... 


변경 방법을 알려드리겠습니다. 



1. 다른 관리자 계정이 있는지 확인하십시오. 이렇게 하지 않으면 관리자(administrator)라는 내장형 사용자를 임시로 활성화할 수 있습니다.


윈도우 키 -> cmd -> 명령프로토콜 (오른쪽 클릭) -> 해당 폴더 열기 ->

 명령 프로토콜 (오른쪽 클릭) -> 관리자 권한으로 실행



명령창에 아래 명령어 실행.

net user administrator /active:yes


영어 및 한국어가 아닌 버전의 Windows 10을 사용하는 경우 관리자 계정 이름이 달라집니다. 예를 들어 프랑스어 버전의 경우 기본 제공 관리 계정의 사용자 이름은 "Administradur"이며 스페인어 인 "Administrador"입니다. 따라서 정확한 사용자 이름을 지정해야합니다. 그렇지 않으면 "사용자 이름을 찾을 수 없습니다"라는 오류 메시지가 나타납니다! 올바른 사용자 이름을 찾으려면 명령 줄 창에서 net user를 입력하고 Enter 키를 누릅니다.


2. PC 사용자 로그아웃을 하거나 PC를 재부팅합니다.


3 다른 계정에 로그인: Administrator

별도의 비밀번호 없이 로그인이 됩니다.


4.사용자 폴더(기본 값으로 C:\Users)로 이동하여 사용자 폴더의 이름을 원하는 대로 변경합니다.



5. 레지스트리 편집기 시작:

(윈도우 키 + R ) -> regedit -> OK


HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\

방금 이름을 변경한 프로파일과 관련된 키를 찾은 다음 ProfileImagePath 값을 찾아 새 경로의 이름을 변경합니다.



6. 추가 단계. 경로를 프로파일로 변경 한 후에 오류가 발생하면 수행하십시오. 

레지스트리에서 '이전 계정 이름'을 검색하십시오. 이전 경로로 값을 찾으면 새로운 값으로 변경하십시오.

이전 경로가 포함 된 모든 항목을 수정할 때까지 레지스트리 편집기에서 "F3"키를 누르십시오.


7. 다시 원래의 계정으로 로그인해서 1번의 항목을 반복합니다.

net user administrator /active:no




참조 및 출처 

http://tunecomp.net/rename-user-profile-folder-in-windows-10-c-users/



반응형

한눈에 살펴보는 PostgreSQL


NHN에서는 CUBRID라는 오픈소스 DBMS를 개발하고 있으며 사내외 여러 서비스에 적용해 안정적으로 운영하고 있습니다. 여기서 살펴볼 PostgreSQL도 오픈소스 DBMS며, 여러 나라의 다양한 개발자들의 자발적인 노력으로 개발되고 있습니다. 오픈소스 프로젝트로는 상당히 긴 역사인 15년 이상의 오랜 역사를 가지고 있고 최근에는 1년 여만에 새로운 버전인 9.2 버전을 출시했습니다. 이 글에서는 꾸준히 발전해 가는 PostgreSQL가 어떤 데이터베이스인지 알아보겠습니다.

PostgreSQL을 알아야 할 이유

PostgreSQL(http://www.postgresql.org) 은 북미와 일본에서는 높은 인지도와 많은 인기를 얻고 있는 RDBMS다. 국내에서는 아직 잘 사용하지 않고 있지만, 기능과 성능면에서 매우 훌륭한 RDBMS이기 때문에 PostgreSQL가 어떠한 데이터베이스인지 시간을 들여 알아볼 필요는 있다.

PostgreSQL(포스트-그레스-큐엘 [Post-Gres-Q-L]로 발음)은 객체-관계형 데이터베이스 시스템(ORDBMS)으로, 엔터프라이즈급 DBMS의 기능과 차세대 DBMS에서나 볼 수 있을 법한 많은 기능을 제공하는 오픈소스 DBMS다. 실제 기능적인 면에서는 Oracle과 유사한 것이 많아, Oracle 사용자들이 가장 쉽게 적응할 수 있는 오픈소스 DBMS가 PostgreSQL이라는 세간의 평 또한 많다.

역사

PostgreSQL의 조상에는 여러 제품이 있는데, 그중 Ingres(INteractive Graphics REtrieval System)는 PostgreSQL의 시조라고 할 수 있다. 이 Ingres는 현재까지도 활발하게 활동하고 있는 데이터베이스 계의 거장 Michael Stonebraker가 시작한 프로젝트다.

postgresql1

그림 1 Michael Stonebraker(원본 출처: https://www.facebook.com/michael.stonebraker)

이 Ingres는 1977년 미국 버클리대학에서 시작한 프로젝트다. 이후 Ingres를 잇는 Postgres(Post-Ingres)라는 또 다른 프로젝트 또한 그의 손을 거쳐 탄생됐다. 1991년 Postgres 버전 3이 출시되면서 많은 사용자를 확보했으나 사용자 지원에 대한 부담이 증가해 결국 프로젝트는 1993년에 종료됐다. 이후에도 Postgres는 현재의 Informix 제품에 상당 부분 영향을 준 것으로 알려져 있다(Postgres를 상용화한 Illustra는 1997년 Informix에 인수됐고 2001년에 Illustra는 IBM에 인수됐다).

postgresql2

그림 2 제품 변천사

하지만 Postgres 사용자와 학생들이 프로젝트 종료 선언과 별개로 Postgres의 개발을 계속 진행했고, SQL 지원과 구조 개선을 통해 Postgres보다 40% 정도 빠른 성능을 보여 주는 Postgres95를 만들어 냈다.

이 Postgre95는 1996년 오픈소스가 되면서 Postgres를 계승했다는 것과 SQL을 지원한다(Postgres는 SQL이 아니라 QUEL이라는 언어를 지원했다)는 것을 반영하기 위해 현재의 PostgreSQL로 이름을 변경한 후 1997년 최초 버전을 6.0으로 정해 PostgreSQL을 출시했다.

이후에도 PostgreSQL은 오픈 소스 커뮤니티에 의해 최근까지도 활발히 개발되고 있으며 2012년 10월 현재 9.2 버전까지 출시됐다.

또한 개방된 라이선스(BSD나 MIT 라이선스와 비슷하게 상용적인 사용과 수정을 허용하며 단, 사용 중 발생하는 문제에 대해 법적 책임이 없음을 명확히 함)의 특징으로 인해 20종 이상의 다양한 분기(fork)가 존재했으며, 그중 많은 수가 PostgreSQL에 다시 영향을 주거나 혹은 사라졌다.

PostgreSQL의 로고는 'Slonik'이라는 이름을 가진 코끼리다. 코끼리를 로고로 사용하게 된 정확한 근원은 찾을 수 없으나 과거의 흔적을 뒤져 보면, 오픈소스화된 직후 한 사용자가 아가사 크리스티의 소설 '코끼리는 기억한다'에서 착안해 제안한 것으로 보인다. 이후 모든 공식적인 자리에서 이 코끼리 로고는 빠지지 않고 등장하게 됐다. 코끼리는 크고 강하고 믿음직하며 기억력이 좋다는 이미지 때문에 Hadoop이나 Evernote도 코끼리를 공식 로고로 사용하고 있다.

postgresql3

그림 3 PostgreSQL의 로고*

기능 및 제한

PostgreSQL은 관계형 DBMS의 기본적인 기능인 트랜잭션과 ACID(Atomicity, Consistency, Isolation, Durability)를 지원한다. 또한 ANSI SQL:2008 규격을 상당 부분 만족시키고 있으며, 전부를 지원하는 것을 목표로 현재도 기능이 계속 추가되고 있다.

또한 PostgreSQL은 기본적인 신뢰도와 안정성을 위한 기능뿐만 아니라 진보적인 기능이나 학술적 연구를 위한 확장 기능도 많이 가지고 있다. PostgreSQL의 기능을 대략적으로 열거해 보더라도 상당히 많은 기능을 가지고 있음을 알게 된다.

  • Nested transactions (savepoints)
  • Point in time recovery
  • Online/hot backups, Parallel restore
  • Rules system (query rewrite system)
  • B-tree, R-tree, hash, GiST method indexes
  • Multi-Version Concurrency Control (MVCC)
  • Tablespaces
  • Procedural Language
  • Information Schema
  • I18N, L10N
  • Database & Column level collation
  • Array, XML, UUID type
  • Auto-increment (sequences),
  • Asynchronous replication
  • LIMIT/OFFSET
  • Full text search
  • SSL, IPv6
  • Key/Value storage
  • Table inheritance

이외에도 엔터프라이즈급 DBMS의 다양한 기능과 새로운 기능을 자랑하고 있다.

PostgreSQL의 일반적인 제한 사항은 아래와 같다.

표 1 기본 제한 사항

항목제한 사항
최대 DB 크기(Database Size)무제한
최대 테이블 크기(Table Size)32TB
최대 레코드 크기(Row Size)1.6TB
최대 컬럼 크기(Field Size)1 GB
테이블당 최대 레코드 개수(Rows per Table)무제한
테이블당 최대 컬럼 개수(Columns per Table)250~1600개
테이블당 최대 인덱스 개수(Indexes per Table)무제한

로드맵

2012년 10월 기준 최신 버전은 9.2이다. PostgreSQL의 발전 과정을 연도별로 간단히 정리하면 <그림 4>와 같이 나타낼 수 있을 것이다.

postgresql4

그림 4 연도별 발전 과정(원본 출처: http://momjian.us/main/writings/pgsql/features.pdf)

버전별 주요 기능은 다음과 같다.

표 2 버전별 주요기능

버전출시주요 기능
0.011995Postgres95 릴리스
1.01995저작권 변경, 오픈소스화
6.0 ~ 6.51997 ~ 1999PostgreSQL로 이름 변경 Index, VIEWs and RULEs Sequences, Triggers Genetic Query Optimizer Constraints, Subselect MVCC, JDBC interface,
7.0 ~ 7.42000 ~ 2010Foreign keys SQL92 syntax JOINs Write-Ahead Log Information Schema, Internationalization
8.0 ~ 8.42005 ~ 2012Microsoft Windows Native 버전 지원 Savepoint, Point-in-time recovery Two-phase commit Table spaces, Partitioning Full text search Common table expressions (CTE) SQL/XML, ENUM, UUID Type Window functions Per-database collation 복제, Warm standby
9.02010-09Streaming 복제, Hot standby Microsoft Windows 64bit 버전 지원 Per-column conditional trigger
9.12011-09기능 차별화 Synchronous 복제 Per-column collations Unlogged tables K-nearest-neighbor indexing Serializable isolation level Writeable CTE (WITH) SQL/MED External Data SE-Linux integration
9.22012-09성능 최적화 linear scalability to 64 cores CPU 전력 소비량 감소 Cascade streaming 복제 JSON, Range Type Lock management 개선 Space-partitioned GiST index Index-only scans (covering)

이후 PostgreSQL 9.3 버전은 2013년 3분기 출시를 목표로 현재 개발이 진행 중이며, 주요 기능으로는 관리 기능 개선, Parallel query 지원, MERGE/UPSERT 지원, Multi-Master 복제, Materialized View 기능, 다중 언어 지원 개선 등이 계획되어 있다. 더 자세한 내용은 http://wiki.postgresql.org/wiki/Todo 에서 살펴볼 수 있다.

내부 구조

PostgreSQL의 프로세스 구조를 간단히 살펴보면 다음과 같다.

postgresql5

그림 5 프로세스 구조

클라이언트는 인터페이스 라이브러리(libpg, JDBC, ODBC 등의 다양한 인터페이스)를 통해 서버와의 연결을 요청(1)하면, Postmaster 프로세스가 서버와의 연결을 중계(2)한다. 이후 클라이언트는 할당된 서버와의 연결을 통해 질의를 수행(3)한다(그림 5).

서버 내부의 질의 수행 과정을 간단히 살펴보면 다음과 같다.

postgresql6

그림 6 쿼리 수행 절차

클라이언트로부터 질의 요청이 들어오면 구문 분석 과정(1)을 통해 Parse Tree를 생성하고 의미 분석 과정(2)를 통해 새로운 트랜잭션을 시작하고 Query Tree를 생성한다.

이후 서버에 정의된 Rule에 따라 Query Tree가 재 생성(3)되고 실행 가능한 여러 수행 계획 중 가장 최적화된 Plan Tree를 생성(4)한다. 서버는 이를 수행(5)하여 요청된 질의에 대한 결과를 클라이언트로 전달하게 된다(그림 6).

서버의 쿼리 수행 과정에서는 데이터베이스 내부의 시스템 카탈로그가 많이 사용되는데, 사용자가 함수나 데이터 타입은 물론 인덱스 접근 방식 및 RULE 등을 시스템 카탈로그에 직접 정의할 수도 있다. 따라서 PostgreSQL에서는 이것이 기능을 새로 추가하거나 확장하는데 있어 중요한 포인트로 활용된다.

데이터가 저장되는 파일들은 여러 개의 페이지들로 구성되며, 하나의 페이지는 확장 가능한 slotted page 구조를 가진다(그림 7, 그림 8).

postgresql7

그림 7 데이터 페이지 구조

postgresql8

그림 8 인덱스 페이지 구조

개발 프로세스

PostgreSQL의 개발 프로세스 모델은 다음의 문장으로 설명할 수 있다.

"소수 주도의 커뮤니티 기반 오픈 소스 프로젝트"

이는 Linux, Apache, Eclipse 프로젝트와 같이 소수의 관리자와 다양한 개발자 그리고 다수의 사용자가 프로젝트 구성원을 이루고 있으며, 소수의 관리자 그룹(Core Team)은 다수의 사용자로부터의 요청과 피드백을 수집(우선순위를 정하기 위해 투표 방식을 활용하기도 한다. 자세한 내용은 http://postgresql.uservoice.com 를 참조한다.)하여 제품의 방향을 결정하고 코드의 최종 승인 및 릴리스 권한을 행사한다(MySQL 또는 JBoss와 같은 기업 관리형 개발프로세스와는 다른 모델로 분류됨).

개발자 그룹은 코드 커미터, 코드 개발자/기여자로 구성되어 있으며 이들은 미국, 일본, 유럽 등의 여러 나라에 분포되어 있다.

다양한 개발자들에 의해 개발된 코드는 다양한 리뷰 과정(Submission Review, Usability Review, Feature Test, Performance Review, Coding Review, Architecture Review, Review Review)과 Core Team의 승인을 거처 제품에 반영이 된다. 커뮤니티에서는 오래 전부터 사용해오던 메일링 리스트가 주로 사용되고 있으며, 매뉴얼을 포함한 다양한 문서들이 공식 홈페이지(http://www.postgresql.org) 에서 잘 관리되고 있다.

경쟁 제품

PostgreSQL은 엔터프라이즈급 상용 데이터베이스와 비교되기를 원하나 주로 유명 오픈소스 DBMS가 비교 대상이 된다. 오픈소스 DBMS의 캐치프레이즈로 제품 특징만을 나열해 보면 다음과 같다.

  • PostgreSQL: The world's most advanced open source database
  • MySQL: The world's most popular open source database
  • Firebird: The true open source database
  • CUBRID: Open Source Database Highly Optimized for Web Applications
  • SQLite: self-contained library, serverless, zero-configuration, transactional SQL database engine

캐치프레이즈만으로 제품을 비교하긴 어려우나 PostgreSQL은 진보와 개방을 표방하고 있음을 알 수 있다.

다음은 PostgreSQL이 경쟁 제품으로 내세우는 제품에 대한 간략한 비교다.

표 3 경쟁 제품 비교

Oracle오랫동안 검증된 방대한 양의 코드, 다양한 레퍼런스. 그러나 비싼 비용이 단점
DB2, MS SQLOracle과 비슷함
MySQL다양한 응용과 레퍼런스. 그러나 기업형 개발 모델과 라이선스 부담
다른 상용 DB오픈소스 DBMS에 의해 세력이 기우는 중
타 오픈소스DB프로젝트에 개발자를 끌어 들이기 위해 힘든 노력 중

이전부터 PostgreSQL 진영은 엔터프라이즈 시장에 진출하려는 시도를 계속 해 왔고, 2004년에는 PostgreSQL을 이용한 전문 기업인 EnterpriseDB(http://www.enterprisedb.com) 가 생겨나 엔터프라이즈 DBMS 시장을 좀 더 확고히 다지기 위한 노력을 기울이고 있다. 대표적인 산출물이 Postgres Plus Advanced Server 제품의 출시다. 이는 오픈 소스 PostgreSQL에 Oracle 호환성 기능(PL/SQL, SQL 구문, 함수, DB Links, OCI 라이브러리 등 지원)과 관리 도구를 추가해 용이한 데이터 및 응용 마이그레이션과 Oracle 대비 20% 이하의 비용 절감을 주무기로 내세우고 있다(그림 10).

postgresql9

그림 10 Oracle 대비 비용 절감 효과(원본 출처)

또한 PostgreSQL 전문가의 교육, 컨설팅, 마이그레이션 및 기술 지원 서비스 등을 제공하는 등의 차별화된 서비스도 제공하며 각종 분야 약 300여 개의 레퍼런스 사이트를 통해 모든 업계에서 사용 가능한 데이터베이스임을 홍보하며 세계 각지에 사용자 층을 늘리고 있는 추세다.

현황, 동향

대부분의 PostgreSQL 사용기를 읽어 보면 알 수 있듯이 PostgreSQL을 사용하는 사람들은 대부분 개발자적인 성향을 가지고 있으며 제품에 대한 애정도와 충성도가 높은 편이다.

그도 그럴 것이 다른 제품과 비교하면 일반적으로 부족하지 않은 기능과 무난한 성능을 가지고 있고, 또 하나 중요한 것은 새로운 개발자를 끌어 들이기에 좋은 입문 조건들을 가지고 있다는 것이다.

프로젝트 페이지에 잘 정리된 매뉴얼, 문서와 300종 이상의 관련 서적, 그리고 세계 각국에서 개최되는 매년 10회 이상의 다양한 세미나와 콘퍼런스 등도 이를 뒷받침하고 있으며 최근에는 전문 잡지까지 등장했다. 이는 모두 왕성한 커뮤니티 활동의 산물이라 할 수 있다.

사용자가 꼽는 PostgreSQL의 대표적인 특징으로는 다음과 같은 것들이 있다.

  • '신뢰도'는 제품의 최우선 사항
  • ACID 및 트랜잭션 지원
  • 다양한 인덱싱 기법 지원
  • 유연한 Full-text search 기능
  • 동시성 성능을 높여주는 MVCC 기능
  • 다양하고 유연한 복제 방식 지원
  • 다양한 프로시져(PL/pgSQL, Perl, Python, Ruby, TCL, 등)/인터페이스(JDBC, ODBC, C/C++, .Net, Perl, Python, 등) 언어
  • 질 좋은 커뮤니티 지원 및 상업적인 지원
  • 잘 만든 문서 및 충분한 매뉴얼 제공

그리고, 다양한 확장 기능과 확장 기능 개발의 용이성 등이 있으며 PostgreSQL만의 차별화된 확장 기능으로 다음과 같은 것들이 있다.

  • GIS add-on 지원 (PostGIS)
  • Key-Value 스토어 확장 기능 (HStore)
  • DBLink 기능
  • Crypto, UUID 등 다양한 함수, 타입 지원

이외에도 실용적이거나 실험적인 많은 확장 기능들이 있다.

이중 최근 들어 많이 회자되는 GIS(Geographic Information System) 기능에 대해 간략히 살펴보자. PostGIS(http://postgis.refractions.net) 는 PostgreSQL에 OpenGIS 규격(http://www.opengeospatial.org/standards/sfs) 을 준수하며 Geographic object를 지원 가능하게 하는 미들웨어 형태의 확장 기능이다(그림 11). 2001년부터 개발됐으며 많은 기능과 성능 개선을 통해 오픈 소스로는 가장 많은 사용자를 확보하고 있다. 상용 제품으로는 Oracle Spatial, DB2, MS SQL Server 등도 있으나 비용 대 성능 측면에서 상용 제품은 그다지 환영 받지 못하고 있다.

게다가 PostGIS/PostgreSQL의 제공 기능이나 성능은 Oracle과 비견할만하다는 벤치마크 자료를 어렵지 않게 구할 수 있다.

postgresql10

그림 11 PostGIS 구조

그리고 최근 동향을 살펴보면 GIS 분야 외에도 클라우드와 관련해서도 PostgreSQL가 많이 회자되고 있다. 최근 DbaaS(DB As A Service)를 제공하는 기업이 늘어나면서 비용과 라이선스 측면에서 유리한 PostgreSQL에 대한 수요가 증가했고 EnterpriseDB 사는 이에 맞추어 클라우드 시장을 겨냥하여 다음의 특징을 갖는 Postgres Plus Cloud Database 제품을 출시했다.

  • Simple setup & web-based management
  • Automatic scaling, load balancing and failover
  • Automated online backup
  • Database Cloning

이는 Amazon EC2, Eucalyptus cloud, Red Hat Openshift development platform cloud 등에서 사용되며 다른 Heroku, dotCloud 등의 많은 클라우드 서비스 업체에서도 PostgreSQL을 사용하는 서비스를 제공하고 있다.

마치며

MySQL을 인수했던 Sun이 2009년 Oracle에 인수되면서 좀더 폐쇄적인 기업형 프로젝트 성향을 보이고 비슷한 시기에 많은 수의 MySQL 개발자들이 떠나게 되자 이를 불안해 하는 MySQL 사용자들은 손쉽게 이전할 수 있는 MySQL의 fork(MariaDB, Drizzle, Percona 등)뿐만 아니라 20년 이상 잘 지속되어 개발되고 있는 PostgreSQL으로의 이전에도 신경을 쓰고 있는 듯 하다.

미국의 유명한 취업 포털 회사인 indeed(http://www.indeed.com) 의 PostgreSQL과 MySQL 관련 업무에 대한 구인 증가율 추이(그림 9)를 보면, 2011년 들어서는 MySQL의 구인 증가율이 한풀 꺾인 듯 보이나 PostgreSQL 업무 구인은 꾸준히 증가하고 있는 것으로 보인다.

postgresql11

그림 12 indeed의 구인 증가율 추이(원본 출처)

검색 사이트에서의 검색 빈도를 보면 MySQL의 추세가 지속적으로 줄어들고 있고 전체적으로 PostgreSQL의 추이는 거의 변동이 없는 것으로 보이나 국내에서는 2010년 중반 이후 지속적인 증가 추세를 보이고 있다.

물론 아직까지도 PostgreSQL 보다는 MySQL의 인기도나 사용률이 월등히 높은 편이다. 이런 추이들로 정확한 현황이나 향후 추세를 알 수는 없겠지만 대략적으로는 MySQL의 인기도가 하락하면 PostgreSQL의 인기도가 상승할 것이라고 짐작할 수는 있을 것이다.

아직은 MySQL의 인기도를 꺾을 파괴력을 지니지는 않았으나, 이를 대비하여 PostgreSQL 오픈 소스 프로젝트 진영에서는 다음과 같은 노력을 지속적으로 하고 있으며

  • 기본적인 DBMS 기능의 신뢰도 증대
  • 진보적이며 차별화된 기능 확장
  • 오픈 소스 개발자의 지속적 확충

또한 비지니스의 목적이 강한 EnterpriseDB 진영에서는 다음과 같은 행보가 지속적으로 이루어 지고 있다.

  • 엔터프라이즈 시장에서의 영역 확대
  • 클라우드 시장에서의 영역 확대
  • Oracle 및 MySQL을 대체하기 위한 노력


반응형

Button클릭 시 image/* 파일들 선택할 수 있는 창 열기

<요약>

OnCreate 부문에 Button onClickListener을 추가 하고, Intent를 활용하여 

전체적인 파일을 가져올 수 있게 합니다.

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button openimg = (Button)findViewById(R.id.openimg);
openimg.setOnClickListener(new Button.OnClickListener(){
public void onClick(View view){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivity(intent);
}
});

}


때때로 Android애플리케이션에서 사용자가 선택한 후에 응용 프로그램에 의해 표시되는 갤러리에서 이미지를 선택할 수 있는 갤러리에서 이미지를 선택할 수 있습니다.

이 글에서는 사용자가 모든 앱에서 이미지를 선택할 수 있는 단일 인터페이스를 호출하는 방법을 살펴보겠습니다.(예:갤러리, 사진, ESFileExplorer등)및 폴더(GoogleDrive, 최근, 다운로드 등)를 인첸트를 사용합니다.



갤러리 이미지 갤러리 시작


사용자가 다음과 같은 의도로 다음과 같은 의도를 사용할 수 있도록 하려면 사용자가 이미지를 선택할 수 있습니다.

Intent intent = new Intent();
// Show only images, no videos or anything else
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
// Always show the chooser (if there are multiple options available)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);


PICK_IMAGE_REQUEST는 인스턴스 변수로 정의된 요청 코드입니다.

private int PICK_IMAGE_REQUEST = 1;


Activity/Fragment에서 선택한 영상 표시

일단 선택이 이루어지면 ImageView 사용자 인터페이스에서 이미지를 플립 차트에 표시합니다.

이를 위해서는 onActivityResult()를 오버 라이드 해야 합니다.


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
 
    if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
 
        Uri uri = data.getData();
 
        try {
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
            // Log.d(TAG, String.valueOf(bitmap));
 
            ImageView imageView = (ImageView) findViewById(R.id.imageView);
            imageView.setImageBitmap(bitmap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

이렇게 배치하려면 다음과 같은 작업을 수행해야 합니다.

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageView" />


갤러리에서 선택할 때 선택한 사진이 UI에 표시되고 선택한 사진이 어떻게 표시되는지 확인할 수 있습니다.


컨텐츠 URI에서 절대 파일 경로 가져오기


Uri uri = data.getData();
String[] projection = { MediaStore.Images.Media.DATA };
 
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
cursor.moveToFirst();
 
Log.d(TAG, DatabaseUtils.dumpCursorToString(cursor));
 
int columnIndex = cursor.getColumnIndex(projection[0]);
String picturePath = cursor.getString(columnIndex); // returns null
cursor.close();


그러면 커서에서 반환된 MediaStore.Images.Media.DATA 값이 null이라는 것을 알 수 있습니다.

이 문제(및 수정 사항)는 다음과 같은 스레드 스레드에서 해결되었습니다.


Button클릭 시 image/* 파일들 선택할 수 있는 창 열기

<요약>

OnCreate 부문에 Button onClickListener을 추가 하고, Intent를 활용하여 

전체적인 파일을 가져올 수 있게 합니다.

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Button openimg = (Button)findViewById(R.id.openimg);
openimg.setOnClickListener(new Button.OnClickListener(){
public void onClick(View view){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivity(intent);
}
});

}


때때로 Android애플리케이션에서 사용자가 선택한 후에 응용 프로그램에 의해 표시되는 갤러리에서 이미지를 선택할 수 있는 갤러리에서 이미지를 선택할 수 있습니다.

이 글에서는 사용자가 모든 앱에서 이미지를 선택할 수 있는 단일 인터페이스를 호출하는 방법을 살펴보겠습니다.(예:갤러리, 사진, ESFileExplorer등)및 폴더(GoogleDrive, 최근, 다운로드 등)를 인첸트를 사용합니다.



갤러리 이미지 갤러리 시작


사용자가 다음과 같은 의도로 다음과 같은 의도를 사용할 수 있도록 하려면 사용자가 이미지를 선택할 수 있습니다.

Intent intent = new Intent();
// Show only images, no videos or anything else
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
// Always show the chooser (if there are multiple options available)
startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE_REQUEST);


PICK_IMAGE_REQUEST는 인스턴스 변수로 정의된 요청 코드입니다.

private int PICK_IMAGE_REQUEST = 1;


Activity/Fragment에서 선택한 영상 표시

일단 선택이 이루어지면 ImageView 사용자 인터페이스에서 이미지를 플립 차트에 표시합니다.

이를 위해서는 onActivityResult()를 오버 라이드 해야 합니다.


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
 
    if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
 
        Uri uri = data.getData();
 
        try {
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
            // Log.d(TAG, String.valueOf(bitmap));
 
            ImageView imageView = (ImageView) findViewById(R.id.imageView);
            imageView.setImageBitmap(bitmap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

이렇게 배치하려면 다음과 같은 작업을 수행해야 합니다.

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageView" />


갤러리에서 선택할 때 선택한 사진이 UI에 표시되고 선택한 사진이 어떻게 표시되는지 확인할 수 있습니다.


컨텐츠 URI에서 절대 파일 경로 가져오기


Uri uri = data.getData();
String[] projection = { MediaStore.Images.Media.DATA };
 
Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
cursor.moveToFirst();
 
Log.d(TAG, DatabaseUtils.dumpCursorToString(cursor));
 
int columnIndex = cursor.getColumnIndex(projection[0]);
String picturePath = cursor.getString(columnIndex); // returns null
cursor.close();


그러면 커서에서 반환된 MediaStore.Images.Media.DATA 값이 null이라는 것을 알 수 있습니다.

이 문제(및 수정 사항)는 다음과 같은 스레드 스레드에서 해결되었습니다.

요청에 의해 호출된 앱에서 다양한 섹션(탐색 드로어에 있는)을 선택할 때마다 다양한 종류의 Content URIs가 반환됩니다.

갤러리(앱)섹션의 선택 항목에서 얻을 수 있는 것은 다음과 같습니다.

Recents(또는 일반적으로 내 생각)에서는 다음과 같은 이점을 얻을 수 있습니다.

GoogleDrive에서 선택할 때는 다음과 같은 URI를 사용합니다.

또한 사진(앱)섹션에서 다음을 수행합니다(URL인코딩됨).





버튼 위치 내가 원하는 곳에 설정하기

처음 만들면 스튜디오 안에서는 정상작동하나, 핸드폰을 활용할 시 error문구와 함꼐 0,0으로 이동이 됩니다.

<Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        tools:layout_editor_absoluteX="62dp"
        tools:layout_editor_absoluteY="310dp" />


이 구문을 

<Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.291" />

와 같이 설정하고, 디자인 부분에서 위치를 조절해준다면 원하는 위치에 배열할 수 있습니다.





반응형

Q

사람들이 'public static final String mystring = ~~~' 을 작성한 다음 많은 값을 사용하는 코드를 보았습니다.


왜 그들은 그것을해야하나요? 왜 그들은 그것을 사용하기 전에 최종 값으로 초기화해야합니까?

그 핵심 (public static final)의 의미를 이해합니다.

내가 이해하지 못하는 것은 상수가 

한 곳에서만 사용되고 같은 클래스에서만 사용 되더라도 사람들이 왜 그것을 사용하는지에 대한 것입니다. 

그것을 선언하는 이유는 무엇입니까? 왜 우리는 변수를 사용하지 않습니까?


A

final은 변수의 값이 변경되지 않음을 나타냅니다. 즉, 값을 선언 한 변수는 선언 된 후에 수정할 수 없습니다.


public final static String 을 사용하면 다음과 같은 String을 만들 수 있습니다.

1. 클래스 (static : 그것을 사용하는 데 필요한 인스턴스가 없음)에 속하며,

2. 클래스의 모든 인스턴스와 클래스를 사용하는 다른 객체에서 사용할 수있는
   String 상수를 정의하려는 경우와 같이 변경되지 않습니다 (final).


ex)

public final static String MY_CONSTANT = "SomeValue";

// ... 다른 코드에서 다른 객체에 상수를 사용합니다.
if (input.equals(MyClass.MY_CONSTANT)

비슷하게

public static final int ERROR_CODE = 127;


즉,

final을 사용할 필요는 없지만 프로그램 실행 중에 실수로 변경되는 상수를 유지하고 변수가

상수라는 표시기로 사용됩니다.


final 상수가 현재 클래스 및 또는 한 곳에서만 사용되는 경우에도 모든 상수를 최종으로 선언하는 것이 좋습니다.

final : 코드의 수명이 다할 때까지 상수가 여러 곳에서 사용될 수 있습니다.

또한 final을 사용하면 구현시 일부 최적화를 수행 할 수 있습니다.




+ 다른 답변 해석

static 이란 클래스를 인스턴스화하거나 객체를 사용하지 않고도 사용할 수 있습니다.

final은 문자열 상수를 만드는데 사용되는 키워드입니다. 해당 문자열의 값은 변경할 수 없습니다.

 아래 예를보세요.

  public class StringTest { 
           static final String str = "Hello"; 
  public static void main(String args[]) { 
           // str = "world"; // 주석을 해제하면 에러가 발생할 것입니다.
           System.out.println(str); // called without the help of an object                       
           System.out.println(StringTest.str);// called with class name  
             } 
         } 


반응형

Traceback (most recent call last):

  File "binfilemaking.py", line 5, in <module>

    import matplotlib.pyplot as plt

  File "/usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 115, in <module>

    _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()

  File "/usr/local/lib/python2.7/dist-packages/matplotlib/backends/__init__.py", line 32, in pylab_setup

    globals(),locals(),[backend_name],0)

  File "/usr/local/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.py", line 6, in <module>

    from six.moves import tkinter as Tk

  File "/home/testguest/.local/lib/python2.7/site-packages/six.py", line 203, in load_module

    mod = mod._resolve()

  File "/home/testguest/.local/lib/python2.7/site-packages/six.py", line 115, in _resolve

    return _import_module(self.mod)

  File "/home/testguest/.local/lib/python2.7/site-packages/six.py", line 82, in _import_module

    __import__(name)

  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 42, in <module>

    raise ImportError, str(msg) + ', please install the python-tk package'

ImportError: No module named _tkinter, please install the python-tk package


라는 에러가 발생하였습니다. 이제 해결하는 방법을 알아보겠습니다.


시스템에서 제공하는 Python과 함께 사용하기 위해 로컬에서 Tkinter를 설치하는 것은 그리 쉽지 않습니다.


소스에서 빌드 할 수도 있지만, 이것은 가장 좋은 아이디어는 아닙니다.

일반적으로 실행중인 바이너리 패키지 기반 배포판에서....


apt-get python-tk 를 컴퓨터에 설치하는 것이 더 안전합니다. (Ubuntu와 같은 데비안에서 파생 된 배포판에서 작동하며 다른 배포판의 패키지 관리자 및 패키지 목록을 참조하십시오.)

그러면 리눅스에서

sudo apt-get install python-tk

를 입력합니다.

그러면 설치 진행 Y를 하시면 해결됩니다.


반응형

'Computer_IT > Python' 카테고리의 다른 글

Python Requests 설치하기 및 크롤링(scraping) 예제  (0) 2017.05.12

matplotlib 설치하기

  -- png, freetype 에 대한 사전 설치 요함.


sudo apt-get install libpng-dev

sudo apt-get install libfreetype6-dev


sudo apt-get install libjpeg8-dev

     ---> jpeg 도 그냥 설치함.. 


sudo pip install matplotlib


반응형

+ 지난 텐서플로우 게시글에 이어서 튜토리얼 2를 진행하겠습니다.

+ 적힌 부분이 추가설명 및 의견입니다.. ㅎㅎ


  기계 학습에 대한 자세한 내용은이 튜토리얼의 범위를 벗어난다. 

그러나 TensorFlow는 손실 함수를 최소화하기 위해 각 변수를 천천히 변경하는 옵티 마이저를 제공합니다.

 가장 간단한 옵티 마이저는 그래디언트 디센트입니다. 

해당 변수에 대한 손실 파생의 크기에 따라 각 변수를 수정합니다. 일반적으로 심볼릭 파생물을 수동으로 계산하는 것은 지루하고 오류가 발생하기 쉽습니다. 

결과적으로 TensorFlow는 tf.gradients 함수를 사용하여 모델 설명 만 제공된 파생물을 자동으로 생성 할 수 있습니다. 단순화를 위해 일반적으로 옵티마이 저가이를 수행합니다. 


+ 마땅한 번역할 단어가 안떠올라서 마지막 구글 번역을 돌렸더니 단어가 이상하네요 추가적으로 예제 코드를 보면서 설명하겠습니다.


예를 들어,


optimizer = tf.train.GradientDescentOptimizer(0.01)
train
= optimizer.minimize(loss)
sess.run(init) # reset values to incorrect defaults.
for i in range(1000):
  sess
.run(train, {x:[1,2,3,4], y:[0,-1,-2,-3]})

print(sess.run([W, b]))



이제 실제 기계 학습을했습니다!

+ 이번 코드는 GradientDescentOptimizer 0.01비율로 손실을 최소화 시키고 선형 모델인 

+ y = Wx+b 에서 x값과 y값을 주어졌을 때, W와, b의 값을 1000번의 학습된 결과를 통해 

+ 값을 표현한 것입니다.


 이 간단한 선형 회귀를 수행하더라도 TensorFlow 핵심 코드가 많이 필요하지는 않지만 모델에 데이터를 입력하는 더 복잡한 모델과 메서드는 더 많은 코드가 필요합니다.

 따라서 TensorFlow는 일반적인 패턴, 구조 및 기능에 대해 더 높은 수준의 추상화를 제공합니다. 

우리는 이어서 이러한 추상화를 사용하는 방법을 배웁니다.


완료된 프로그램 

완성 된 훈련 가능한 선형 회귀 모델은 다음과 같습니다.


import numpy as np
import tensorflow as tf

# Model parameters
W
= tf.Variable([.3], tf.float32)
b
= tf.Variable([-.3], tf.float32)
# Model input and output
x
= tf.placeholder(tf.float32)
linear_model
= W * x + b
y
= tf.placeholder(tf.float32)
# loss
loss
= tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer
= tf.train.GradientDescentOptimizer(0.01)
train
= optimizer.minimize(loss)
# training data
x_train
= [1,2,3,4]
y_train
= [0,-1,-2,-3]
# training loop
init
= tf.global_variables_initializer()
sess
= tf.Session()
sess
.run(init) # reset values to wrong
for i in range(1000):
  sess
.run(train, {x:x_train, y:y_train})

# evaluate training accuracy
curr_W
, curr_b, curr_loss  = sess.run([W, b, loss], {x:x_train, y:y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))



+ 이 코드의 함수를 시각화 해서 본다면

TensorBoard final model visualization



tf.contrib.learn


tf.contrib.learn은 다음을 포함하여 기계 학습의 메커니즘을 단순화하는 상위 TensorFlow 라이브러리입니다.

-실행중인 학습 루프

-평가 루프 실행

-데이터 세트 관리

-수유 관리

tf.contrib.learn은 많은 공통 모델을 정의합니다.


기본 사용법

tf.contrib.learn을 사용하면 선형 회귀 프로그램이 얼마나 단순 해지는 지 주목하십시오


import tensorflow as tf
# NumPy is often used to load, manipulate and preprocess data.
import numpy as np

# Declare list of features. We only have one real-valued feature. There are many
# other types of columns that are more complicated and useful.
features
= [tf.contrib.layers.real_valued_column("x", dimension=1)]

# An estimator is the front end to invoke training (fitting) and evaluation
# (inference). There are many predefined types like linear regression,
# logistic regression, linear classification, logistic classification, and
# many neural network classifiers and regressors. The following code
# provides an estimator that does linear regression.
estimator
= tf.contrib.learn.LinearRegressor(feature_columns=features)

# TensorFlow provides many helper methods to read and set up data sets.
# Here we use `numpy_input_fn`. We have to tell the function how many batches
# of data (num_epochs) we want and how big each batch should be.
x
= np.array([1., 2., 3., 4.])
y
= np.array([0., -1., -2., -3.])
input_fn
= tf.contrib.learn.io.numpy_input_fn({"x":x}, y, batch_size=4,
                                              num_epochs
=1000)

# We can invoke 1000 training steps by invoking the `fit` method and passing the
# training data set.
estimator
.fit(input_fn=input_fn, steps=1000)

# Here we evaluate how well our model did. In a real example, we would want
# to use a separate validation and testing data set to avoid overfitting.
print(estimator.evaluate(input_fn=input_fn))



 {'global_step': 1000, 'loss': 1.9650059e-11}

+ 위 처럼 결과가 나올 것입니다.



커스텀 모델


tf.contrib.learn은 사용자를 미리 정의 된 모델로 잠그지 않습니다. 

TensorFlow에 내장되어 있지 않은 커스텀 모델을 만들고 싶다고 가정 해 보겠습니다. 

tf.contrib.learn의 데이터 세트, 수유, 교육 등의 높은 수준의 추상화는 여전히 유지할 수 있습니다. 

설명을 위해, 우리는보다 낮은 수준의 TensorFlow API에 대한 지식을 사용하여 LinearRegressor에 대한 자체 등가 모델을 구현하는 방법을 보여줍니다.


tf.contrib.learn과 작동하는 사용자 정의 모델을 정의하려면 tf.contrib.learn.Estimator를 사용해야합니다. tf.contrib.learn.LinearRegressor는 실제로 tf.contrib.learn.Estimator의 하위 클래스입니다. 

Estimator를 하위 분류하는 대신 Estimator에게 예측, 교육 단계 및 손실을 평가할 수있는 방법을 

tf.contrib.learn에게 알려주는 model_fn 함수를 제공하기 만하면됩니다. 코드는 다음과 같습니다.


import numpy as np
import tensorflow as tf
# Declare list of features, we only have one real-valued feature
def model(features, labels, mode):
 
# Build a linear model and predict values
  W
= tf.get_variable("W", [1], dtype=tf.float64)
  b
= tf.get_variable("b", [1], dtype=tf.float64)
  y
= W*features['x'] + b
 
# Loss sub-graph
  loss
= tf.reduce_sum(tf.square(y - labels))
 
# Training sub-graph
  global_step
= tf.train.get_global_step()
  optimizer
= tf.train.GradientDescentOptimizer(0.01)
  train
= tf.group(optimizer.minimize(loss),
                   tf
.assign_add(global_step, 1))
 
# ModelFnOps connects subgraphs we built to the
 
# appropriate functionality.
 
return tf.contrib.learn.ModelFnOps(
      mode
=mode, predictions=y,
      loss
=loss,
      train_op
=train)

estimator
= tf.contrib.learn.Estimator(model_fn=model)
# define our data set
x
= np.array([1., 2., 3., 4.])
y
= np.array([0., -1., -2., -3.])
input_fn
= tf.contrib.learn.io.numpy_input_fn({"x": x}, y, 4, num_epochs=1000)

# train
estimator
.fit(input_fn=input_fn, steps=1000)
# evaluate our model
print(estimator.evaluate(input_fn=input_fn, steps=10))




커스텀 모델 () 함수의 내용이 저수준 API의 수동 모델 트레이닝 루프와 얼마나 흡사한지 주목하십시오.



다음 단계


이제 TensorFlow의 기본 지식을 습득했습니다. 우리는 더 많은 것을 배우기 위해 여러분이 볼 수있는 튜토리얼을 몇 가지 더 가지고 있습니다. 초보자의 경우 초보자 인 경우 MNIST를 참조하십시오. 그렇지 않은 경우 전문가를위한 Deep MNIST를 참조하십시오


+ 다음 튜토리얼은 손글씨 인식을 하는 것입니다.

+ 이번 튜토리얼에서는 API에서 얼만큼 잘 제공해주는지 알려주는 것 같았습니다.

+ 다음 튜토리얼 부터는 점점 머신러닝과 관련하여 인곤지능과 가까워질 것 입니다. 

+ 다 같이 힘내봅시다.








반응형

[MYSQL] SELECT 한 내용 INSERT 시키는 방법

Select 한 내용을 그대로 Insert 시키는 방법과 약간 응용하는 법을 소개합니다. 처음에는 저도 방법이 정확히 떠오르지 않아 구글링을 했지만 간단명료하게 나와있는 글이 없어 시간을 좀 뺐겼던 기억이 납니다.

1. select 한 내용의 전체 컬럼 Insert

당연한 이야기지만 select하는 테이블과 insert할 테이블의 컬럼은 일치해야 합니다.

 

2. 원하는 컬럼만 select 해서 Insert

PRIMARY키가 있어 1번의 방법으로 INSERT가 안되는 경우 PRIMARY키를 제외한 컬럼을 직접 선택해서 INSERT하는 방법입니다.


++

위의 글을 참조한 이유는 잘 동작하던 쿼리문이

UID를 추가한 이후 

Column count doesn't match value count at row 1 의 에러 문구가 나왔었다.

실제 소스를 보면서 설명하겠습니다.


insert into HPG

select system, cbroff, consl from CNS

where system = system ; 


일 경우 에러가 없던 문구에서

Column (UID)를 추가하였습니다. 했더니 에러 문구가 위의 msgbox로 출력되었습니다.


즉 From table과 Insert Table의 컬럼 수가 일치하지 않다는 것으로 판단됩니다.


따라서, UID는 자동 증가이기 때문에


insert into HPG(system, cbroff, consl)

select system, cbroff, consl from CNS

where system = system ;


를 추가 함으로 써 에러를 수정할 수 있었습니다.

반응형

'Computer_IT > MySQL' 카테고리의 다른 글

[DB] 인덱스 란? / 인덱스 유,무 의 차이점  (0) 2017.05.24

리눅스 CMOS -- 시간 확인


 CMOS 시간 확인 

# clock -r    


시스템 시간 확인 

# date        


# date +%Y-%m-%d

2011-11-23


CMOS -- 시간 설정

 시스템시간을 CMOS시간으로 설정 

# clock -w   

 CMOS시간을 시스템시간으로 설정 

# clock -s    


리눅스 -- 시간 동기화


리눅스 시스템 시간 동기화 

# rdate -s time.bora.net  


시간 확인 

# date                          


 CMOS 시간에 적용 

# clock -w                   


반응형

+ Recent posts