728x90

 

https://beomseok95.tistory.com/89

 

Kotlin - null 가능성, lateinit ,lazy

Kotlin - null 가능성, lateinit, lazy null 가능성 기본적으로 객체를 불변으로 보고 null값을 허용하지 않습니다. null값을 호용하려면 별도의 연산자가 필요하고 null을 허용한 자료형을 사용할 때도 별도

beomseok95.tistory.com

 

null 가능성

기본적으로 객체를 불변으로 보고 null값을 허용하지 않습니다.

null값을 호용하려면 별도의 연산자가 필요하고 null을 허용한 자료형을 사용할 때도 별도의 연산자들을 사용하여 안전하게 호출해야 합니다.

 

null 허용?

코틀린에서 기본적으로 null 값을 허용하지 않습니다 .따라서 모든 객체는 생성과 동시에 값을 대입하여 초기화 해야합니다.

 

아래 코드는 초기화 하지 않아 에러가 발생합니다.

 

val a:String

에러 Property must be initialized or be abstract

Compilation Error

 

다음 코드는 null 값으로 초기화 해서 에러가 발생합니다.

 

val a: String =null

Null can not be a value of a non-null type String

Compilation Error

 

코틀린에서 null 값을 허용하려면 자료형의 오른쪽에 ? 기호를 붙여주면 됩니다.

아래 코드는 null값을 허용하는 String 객체이기 때문에 에러가 발생하지 않습니다.

 

val a:String=null

 

자바에서는 int, long, double과 같은 프리미티브 자료형은 null 값을 허용하지 않습니다만,

그외 모든 클래스형 변수는 null값을 허용합니다.

 

 

lateinit 키워드를 사용한 늦은 초기화

안드로이드를 개발할 때는 초기화를 나중에 할 경우가 있습니다. 이때는 lateinit 키워드를 변수 선언 앞에 추가하면 됩니다. 안드로이드에서는 특정 타이밍에 객체를 초기화할 때 사용합니다.

초기화를 잊는다면 잘못된 null값을 참조하여 앱이 종료될 수 있으니 주의해야 합니다.

lateinit var a:String //OK

 

="hello"

println(a) //hello

 

 

 

lateinit은 다음 조건에서만 사용할 수 있습니다

1) var 변수에서만 사용합니다.

2) null 값으로 초기화 할 수 없습니다.

3) 초기화 전에는 변수를 사용할 수 없습니다

4) Int, Long, Double, Float에는 사용할 수 없습니다.

 

 

lazy로 늦은 초기화

lateinit이 var로 선언한 변수의 늦은 초기화라면 lazy는 값을 변경할 수 없는 val을 사용할 수 있습니다. val 선언 뒤에 by lazy 블록에 초기화에 필요한 코드를 작성합니다. 마지막 줄에는 초기화 할 값을 작성합니다. 마지막 줄에는 초기화 할 값을 작성합니다.

str이 처음 호출될 때 초기화 블록의 코드가 실행됩니다. println() 메소드로 두번 호출하면 처음에만 "초기화"가 출력됩니다.

val str:String by lazy{

        println("초기화")

        "hello"

}

 

println(str) // 초기화; hello

println(str) //hello

 

lazy로 늦은 초기화를 하면 앱이 시작될 때 연산을 분산시킬 수 있어 빠른 실행에 도움이 됩니다.

 

 

lazy는 다음 조건에서만 사용할 수 있습니다.

1) val 에서만 사용합니다.

 

조건이 적기 때문에 상대적으로 lateinit 보다 편하게 사용할 수 있습니다.

728x90
728x90

안드로이드 기기에서 자료를 저장하는 방법은 크게 다음 4가지가 있다.  (온라인 전송은 논외이므로 제외)

1. 내부저장장치 InternalStorage
2. 외부저장장치 ExternalStorage
3. DB 저장 : SQLite
4. SharedPreferences

 

---------------------------------------------------------------------------------------------
1.안드로이드의 내부저장장치 (InternalStorage)

기본적으로 자바의 파일 입출력 스트림을 사용하며, openFileOutput()  과 openFileInput() 을 사용하여 안드로이드 내부 저장장치 에 파일을 생성하여 쓰고 읽기를 합니다.

 

참고: 외부 저장소 디렉터리와 달리 앱은 이러한 메서드에 의해 반환된 내부 디렉터리를 읽고 쓰는 데 시스템 권한이 필요하지 않습니다.

 

getFilesDir()앱의 내부 디렉터리를 나타내는 File을 반환합니다.

getCacheDir() 앱의 임시 캐시 파일의 내부 디렉터리를 나타내는 File을 반환합니다. 더 이상 필요하지 않은 파일을 모두 삭제하고 언제든지 사용할 수 있는 메모리 양에 관해 합리적인 크기 제한(예: 1MB)을 구현해야 합니다.

주의: 저장용량이 부족하면 시스템은 경고 없이 캐시 파일을 삭제할 수 있습니다.

 

 

Caution: On devices that run Android 7.0 (API level 24) or higher, unless you pass the Context.MODE_PRIVATE file mode into openFileOutput(), a SecurityException occurs.

 

openFileOutput() 메서드에는 파일 모드 매개변수가 필요합니다. MODE_PRIVATE을 전달하면 파일이 비공개로 앱에 전달됩니다. 다른 모드 옵션인 MODE_WORLD_READABLE  MODE_WORLD_WRITEABLE은 API 레벨 17부터 더 이상 사용되지 않습니다. Android 7.0(API 레벨 24)부터는 Android에서 이러한 옵션이 사용되면 SecurityException이 발생합니다. 앱이 다른 앱과 비공개 파일을 공유해야 한다면 FLAG_GRANT_READ_URI_PERMISSION 속성과 함께 FileProvider를 대신 사용해야 합니다. 자세한 내용은 파일 공유를 참조하세요.

Android 6.0(API 레벨 23) 이하에서는 누구든지 읽을 수 있도록 파일 모드(MODE_WORLD_READABLE)를 설정하면 다른 앱이 내부 파일을 읽을 수 있습니다. 하지만 다른 앱이 개발자 앱의 패키지 이름 및 파일 이름을 알아야 읽을 수 있습니다. 파일을 읽기 가능 또는 쓰기 가능으로 명시적으로 설정하지 않으면 다른 앱은 개발자 앱의 내부 디렉터리를 탐색할 수 없으며 읽기 또는 쓰기 권한도 갖지 못합니다. 따라서 내부 저장소의 파일에 MODE_PRIVATE을 사용하는 한 다른 앱이 이러한 파일에 액세스할 수 없습니다.

 

Reference

https://codedragon.tistory.com/353

https://bitsoul.tistory.com/tag/안드로이드저장장치 내부저장장치 InternalStorage openFileInput openFileOutput

https://developer.android.com/training/data-storage/files/internal?hl=ko

 

 

 

728x90
728x90

Reference

wikidocs.net/1153

 

산술 연산자 (Arithmetic Operators):

a = 10, b = 20, c = 3 이라 가정한다.

OperatorDescriptionExample

+ 더하기 a + b = 30
- 빼기 a - b = -10
* 곱하기 a * b = 200
/ 나누기 b / a = 2.0
% 나머지 b % a = 0
** 제곱 a ** c = 1000
// a // c = 3
728x90

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

[Python] from import와 import의 차이  (0) 2020.08.08
728x90

Reference

wikidocs.net/53560

economicslab.tistory.com/m/16108

 

 

머신 러닝에서 식을 세울때 이 식을 가설(Hypothesis)라고 합니다. 보통 머신 러닝에서 가설은 임의로 추측해서 세워보는 식일수도 있고, 경험적으로 알고 있는 식일 수도 있습니다. 그리고 맞는 가설이 아니라고 판단되면 계속 수정해나가게 되는 식이기도 합니다.

선형 회귀의 가설은 이미 널리 알려져있으므로 고민할 필요가 없습니다. 선형 회귀란 학습 데이터와 가장 잘 맞는 하나의 직선을 찾는 일입니다. 이때 선형 회귀의 가설(직선의 방정식)은 아래와 같은 형식을 가집니다.

y=Wx+by=Wx+b

가설의 HH를 따서 yy 대신 다음과 같이 식을 표현하기도 합니다.

H(x)=Wx+bH(x)=Wx+b

이때 xx와 곱해지는 WW를 가중치(Weight)라고 하며, bb를 편향(bias)이라고 합니다.

  • WW bb는 중학교 수학 과정인 직선의 방정식에서 기울기와 y절편에 해당됩니다.
  • 직선의 방정식 링크 : https://mathbang.net/443

 

비용 함수(cost function) = 손실 함수(loss function) = 오차 함수(error function) = 목적 함수(objective function)
특히 비용 함수와 손실 함수란 용어는 기억해두는 것이 좋음

 

수학에서 느낌이라는 표현을 사용하는 것은 아무런 의미도 없습니다. 어떤 직선이 가장 적절한 직선인지를 수학적인 근거를 대서 표현할 수 있어야 합니다. 그래서 오차(error)라는 개념을 도입하겠습니다.

 

위 그림은 임의로 그려진 주황색 선에 대해서 각 실제값(4개의 점)과 직선의 예측값(동일한 x값에서의 직선의 y값)에 대한 값의 차이를 빨간색 화살표 ↕로 표현한 것입니다. 각 실제값과 각 예측값과의 차이고, 이를 각 실제값에서의 오차라고 말할 수 있습니다. 이 직선의 예측값들과 실제값들과의 총 오차(total error)는 어떻게 구할까요? 직관적으로 생각하기에 모든 오차를 다 더하면 될 것 같습니다. 각 오차를 전부 더해봅시다.

 

각 오차를 계산해봤습니다. 그런데 수식적으로 단순히 '오차 = 실제값 - 예측값'으로 정의하면 오차값이 음수가 나오는 경우가 생깁니다. 예를 들어 위의 표에서만 봐도 오차가 음수인 경우가 3번이나 됩니다.

이 경우, 오차를 모두 더하면 덧셈 과정에서 오차값이 +가 되었다가 -되었다가 하므로 제대로 된 오차의 크기를 측정할 수 없습니다. 그래서 오차를 그냥 전부 더하는 것이 아니라, 각 오차들을 제곱해준 뒤에 전부 더하겠습니다.

 

n은 갖고 있는 데이터의 개수를 의미합니다.

이때 데이터의 개수인 n으로 나누면, 오차의 제곱합에 대한 평균을 구할 수 있는데 이를 평균 제곱 오차(Mean Squared Error, MSE)라고 합니다.

 

평균 제곱 오차는 이번 회귀 문제에서 적절한 W b를 찾기위해서 최적화된 식입니다. 그 이유는 평균 제곱 오차의 값을 최소값으로 만드는 W와 b를 찾아내는 것이 가장 훈련 데이터를 잘 반영한 직선을 찾아내는 일이기 때문입니다. ==> 즉 문제를 해결하는 방법

 

평균 제곱 오차를 W b에 의한 비용 함수(Cost function)로 재정의해보면 다음과 같습니다.

cost(W,b)=1ni=1n[y(i)H(x(i))]2cost(W,b)=1n∑i=1n[y(i)−H(x(i))]2

 

다시 정리하겠습니다. Cost(W,b)를 최소가 되게 만드는 W b를 구하면 훈련 데이터를 가장 잘 나타내는 직선을 구할 수 있습니다.

 

 

Q. 음수가 되는걸 방지하기 위해서 왜 오차값을 제곱하는가?

==> 제곱이 아닌 절대값을 쓰면 안되는가? (참고: economicslab.tistory.com/m/16108)

 

주어진 값들이 얼마나 퍼져있는지 정도를 나타내는 지표 중 하나인 분산은 평균과 각 값의 차이를 "제곱"한 평균으로 구한다.
이 식을 볼 때마다, "제곱"을 하지 말고 그냥 "절대값"을 쓰면 되지 않을까? (분산의 제곱 대신, 절대값을 쓴 것을 평균제곱오차라고 부른다)
사실 결론부터 얘기하자면, 현재의 분산을 많이 쓰는 이유는 분산이 unbiased estimator를 구하기 쉽기 때문이다. 실제로 표본분산의 경우는 모분포가 어떤 모양이든지 상관없이 모분산의 unbiased estimator가 되지만, 표본표준편차나 표본절대편차는 그렇지 않다. 

 

 

제곱을 한 것을 최소제곱법(method of least squares) 혹은 평균제곱편차(MSE; Mean Square Error), 절대값을 취한 것을 평균절대편차(MAD; Mean Absolute Deviation)이라고 부름.

 

다음 예를 살펴보자.
1)
True: 60, 64, 67
Predicted: 57, 61, 70
Error = +3, +3, -3
2)
True: 60, 64, 67
Predicted: 59, 65, 73
Error: +1, -1, -6
1)의 경우 MAD= 3, MSE=9로 계산되고,
2)의 경우 MAD=2.67, MSE=12.67로 계산된다.
True가 똑같지만, 아마 추정할 때 쓴 모형이 달랐을 것인데, 1)의 경우에 비해 2)의 경우 MAD가 더 좋게 나타났다.
자세히 살펴보면, Predicted가 True와 차이가 큰 경우가 하나라도 있을 경우 MSE는 큰 패널티를 주는 반면, MAD는 조금은 관대한 결과를 낸다고 볼 수 있다.
상황에 따라 큰 패널티를 주는 것이 맞을 수도, 아닐 수도 있기 때문에, MAD나 MSE 둘 중 무엇이 더 좋은 방법이라고 이야기하기는 어렵다. 이에 대한 충분한 상황 설명이 있어야 하거나, 다양한 지표를 두고 함께 비교해야하는 이유가 여기에 있는 것이다.

 

728x90

+ Recent posts