728x90

자카드 유사도는 Double로 정의한다. 합집합이 0인 경우, 자카드 유사도는 1이 된다. 합집합이 0이 아닌 경우, 자카드 유사도는 교집합 크기 / 합집합 크기이다.

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

처음에는

주어진 문자열을 charAt()으로 한 문자씩 떼어 영문자인지 확인하고,

영문자라면 Stringbuilder에 append하고,

다 했으면 toUpperCase()를 사용해 대문자로 통일하고 시작할까 ? 

생각했었다.

 

그런데 굳이 Stringbuilder로 새로운 문자열을 만들 필요가 없다.

기타 공백이나 숫자, 특수문자가 들어있는 경우는 그 글자 쌍을 버린다는 점을 놓쳐서 복잡하게 생각했다.

문제 풀이의 논리는 다음과 같다.

 

1) 주어진 문자열을 대문자(혹은 소문자)로 통일한다.

 

2) ArrayList로 다중집합 두 개(집합 A, 집합 B)를 만든다.

각 문자열마다 두 개의 문자를 떼어 둘 다 영문자인지 확인하고, 맞다면 다중집합에 넣는다.

 

3)  ArrayList로 두 다중집합의 합집합과 교집합을 만든다.

집합 B의 원소 중 집합 A의 원소와 동일한 원소가 있다면 해당 원소를 교집합 ArrayList에 넣는다. 모든 원소는 합집합 ArrayList에 넣는다.

 

4) 자카드 유사도를 구한다.

자카드 유사도는 Double로 정의한다.

합집합이 0인 경우, 자카드 유사도는 1이 된다. 합집합이 0이 아닌 경우, 자카드 유사도는 교집합 크기 / 합집합 크기이다.

 

5) answer은 자카드 유사도에 65536을 곱한 정수값이다.

 

 

 

다음은 문제 풀이 코드이다.

import java.util.*;

class Solution {
    public int solution(String str1, String str2) {
        int answer = 0;
        
        // 대문자로 통일한다.
        
        str1 = str1.toUpperCase();
        str2 = str2.toUpperCase();
        
        // 다중집합 만들기
        
        ArrayList<String> multiSetA = new ArrayList<>();
        ArrayList<String> multiSetB = new ArrayList<>();
        
        for (int i=0; i<str1.length()-1; i++) {
            char first = str1.charAt(i);
            char second = str1.charAt(i+1);
            
            if (first >= 'A' && first <= 'Z' && second >= 'A' && second <= 'Z') {
                multiSetA.add(first + "" + second);
            }
        }
        
        for (int i=0; i<str2.length()-1; i++) {
            char first = str2.charAt(i);
            char second = str2.charAt(i+1);
            
            if (first >= 'A' && first <= 'Z' && second >= 'A' && second <= 'Z') {
                multiSetB.add(first + "" + second);
            }
        }
        
        Collections.sort(multiSetA);
        Collections.sort(multiSetB);
        
         // 합집합과 교집합 만들기
        
        ArrayList<String> union = new ArrayList<>();
        ArrayList<String> intersection = new ArrayList<>();
        
        for (String s : multiSetA) {
            if (multiSetB.remove(s)) {
                intersection.add(s);
            }
            union.add(s);
        }
        
        for (String s : multiSetB) {
            union.add(s);
        }
        
        // 자카드 유사도 구하기
        
        double jakard = 0;
        
        if (union.size() == 0) {
            jakard = 1;
        }
        else {
            jakard = (double)intersection.size() / (double)union.size();
        }
        
        answer = (int)(jakard * 65536);
        
        return answer;
    }
}

728x90
돋 보 기🔍
728x90

이 문제에서 중요한 포인트는 cache size가 0인 경우를 잊지 말고 생각해야 한다는 점이다. cache size가 0이면 모든 경우는 cachs miss이므로 그냥 cities의 길이에 5를 곱해주면 된다.

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

캐시 교체 알고리즘 LRU를 처음 만났다. 관련 내용을 정리하면서 개념을 익혔다.

 

페이지 교체 알고리즘과 LRU Cache

운영체제는 주기억장치보다 더 큰 용량의 프로그램을 실행하기 위해 프로그램의 일부만 주기억장치에 적재하여 사용한다. 이를 가상메모리 기법이라 한다. 페이징 기법으로 메모리를 관리하는

suebin-log.tistory.com

 

 

Kakao Tech 블로그에서 문제 해설을 보니 이 문제의 정답률은 45.26%이다.

물론 당연하다 . 나도 보자마자 살짝 당황했다 .

신기한 건 문제 풀고, 운영체제 강의 듣는데 바로 LRU 에 대해 배워서 반가웠다 !

 

LRU (Least Recently Used)는 가장 오랫동안 참조하지 않은 페이지를 캐시에서 교체하는 것이다.

LRU 캐시 교체 알고리즘 구현은 보통 Queue, ArrayList, LinkedList를 사용하는 것 같다.

Java에서는 LinkedList가 Queue의 구현체라고 한다.

그래서 LinkedList를 사용했다.

 

아래는 LinkedList 메소드이다.

 

add(Object object)는 LinkedList의 마지막에 데이터를 추가한다.

remove(int index)는 해당 인덱스 위치의 값이 지워지는 것이지만,

remove(Object object)는 해당 값이 없다면 false, 있다면 지우고 true를 반환한다고 한다.

 

이 문제는 세 가지 경우를 생각하면 된다.

 

1) cache size가 0인 경우

 

이 문제에서 중요한 포인트는 cache size가 0인 경우를 잊지 말고 생각해야 한다는 점이다.

cache size가 0이면 모든 경우는 cachs miss이므로 그냥 cities의 길이에 5를 곱해주면 된다.

 

2) cache hit 인 경우

 

3) cache miss 인 경우

 

 

 

아래는 문제 풀이 코드이다.

import java.util.*;

class Solution {
    public int solution(int cacheSize, String[] cities) {
        
        // cache size가 0이면 모든 경우는 cache miss 이다.
        
        if (cacheSize == 0) return cities.length*5;
        
        int answer = 0;
        LinkedList<String> cache = new LinkedList<>();
        
        for (int i=0; i<cities.length; i++) {
            
            // 대문자로 통일한다.
            
            String s = cities[i].toUpperCase();
            
            // cache hit 인 경우 실행시간은 1이다.
            
            if (cache.remove(s)) {
                answer += 1;
                cache.add(s);
            }
            
            // cache miss 인 경우 실행시간은 5이다.
            
            else {
                answer += 5;
                
                if (cache.size() >= cacheSize) {
                    cache.remove(0);
                }
                cache.add(s);
            }
        }
        
        return answer;
    }
}

 

 

 

 

 

728x90
돋 보 기🔍
728x90

운영체제는 주기억장치보다 더 큰 용량의 프로그램을 실행하기 위해 프로그램의 일부만 주기억장치에 적재하여 사용한다. 이를 가상메모리 기법이라 한다. 페이징 기법으로 메모리를 관리하는 운영체제에서 필요한 페이지가 주기억장치에 적재되지 않았을 시(페이지 부재) 어떤 페이지 프레임을 선택하여 교체할 것인지 결정하는 방법을 페이지 교체 알고리즘이라고 한다.

목차

 

페이지 교체 알고리즘 (Page Replacement Algorithm)

 

LRU Cache


페이지 교체 알고리즘 (Page Replacement Algorithm) 

페이지 교체 알고리즘이란 ?

운영체제는 주기억장치보다 더 큰 용량의 프로그램을 실행하기 위해 프로그램의 일부만 주기억장치에 적재하여 사용한다. 이를 가상메모리 기법이라 한다. 페이징 기법으로 메모리를 관리하는 운영체제에서 필요한 페이지가 주기억장치에 적재되지 않았을 시(페이지 부재) 어떤 페이지 프레임을 선택하여 교체할 것인지 결정하는 방법을 페이지 교체 알고리즘이라고 한다.

즉, 필요한 페이지가 메모리에 없을 때 page-fault가 발생하고 Backing Store에서 해당 페이지를 찾아 빈 프레임에 로딩해야 한다. 만약 빈 프레임이 없을 경우 희생 당할 프레임(victim frame)을 고르는 알고리즘이 페이지 교체 알고리즘이다.

페이지 교체 알고리즘은 page-fault 발생 비율을 줄이는 것을 목표로 한다.

 

프레임물리 메모리를 일정한 크기로 나눈 블록
페이지: 가상 메모리를 일정한 크기로 나눈 블록

 

페이지 교체 알고리즘의 종류

  • OPT (Optimal) : 앞으로 가장 오랫동안 사용되지 않을 페이지 교체
  • FIFO (First In First Out) : 가장 오래된 페이지 교체
  • LRU (Least Recently Used) : 가장 오랫동안 사용되지 않은 페이지 교체 = 많은 운영체제가 채택하는 알고리즘
  • LFU (Least Frequently Used) : 참조 횟수가 가장 적은 페이지 교체
  • MFU (Most Frequently Used) : 참조 횟수가 가장 많은 페이지 교체
  • NUR (Not Used Recently) : 최근에 사용하지 않은 페이지 교체

 

OPT 알고리즘

  • 앞으로 가장 오랫동안 사용하지 않을 페이지를 교체하는 알고리즘이다.
  • 모든 페이지 교체 알고리즘 중 page-fault 발생이 가장 적다.
  • Belady`s Anomaly 현상이 발생하지 않는다.
  • 프로세스가 앞으로 사용할 페이지를 미리 알아야한다.
  • 실제로 구현하기 거의 불가능한 알고리즘으로, 연구 목적을 위해 사용된다.
Bealady's Anomaly : 프레임의 개수가 많아져도 page-fault가 줄어들지 않고 늘어나는 현상

 

FIFO 알고리즘

  • 가장 먼저 메모리에 올라온 페이지를 가장 먼저 내보내는 알고리즘이다.
  • 구현이 간단하고, 초기화 코드에 대해 적절한 방법이다.
  • 성능은 좋지 않은 편이다.
  • 들어온 시간을 저장하거나 올라온 순서를 큐를 이용해 저장할 수 있다.
  • Belady`s Anomaly 현상이 발생할 수 있다.

 

LRU (Least Recently Used) 알고리즘

  • 가장 오랫동안 사용하지 않은 페이지를 교체하는 알고리즘이다.
  • 최적 알고리즘과 비슷한 효과를 낼 수 있다.
  • 최적 알고리즘보다 페이지 교체 횟수가 높지만 FIFO 알고리즘보다 효율적이다.
  • 성능이 좋은 편이다.
  • 많은 운영체제가 채택하는 알고리즘이다.

 

LFU (Least Frequently Used) 알고리즘

  • 참조횟수가 가장 적은 페이지를 교체하는 알고리즘이다.
  • 교체 대상이 여러 개라면 가장 오랫동안 사용하지 않은 페이지를 교체한다.

  • 한 페이지를 집중적으로 참조하다가 이후 다시 참조하지 않는 경우 문제가 될 수 있다.
  • 앞으로 사용하지 않아도 초기에 사용된 참조횟수가 높아 메모리에 계속 남아있기 때문이다.
  • 초기에만 쓰인 7이 메모리에 잔존해 낭비가 일어난다.

 

MFU (Most Frequently Used)  알고리즘

  • LFU와 반대로 참조 횟수가 가장 많은 페이지를 교체하는 알고리즘이다.
  • 참조 횟수가 적은 페이지가 최근에 사용된 것이기 때문에 앞으로 사용될 가능성이 높다는 판단이다.
LFU와 MFU는 실제 잘 사용하지 않는다.
구현에 상당한 비용이 들고, 최적 페이지 교체 정책을 (LRU만큼) 제대로 유사하게 구현하지 못하기 때문이다.

LRU Cache

캐시 (Cache)

캐시는 연산에 필요한 데이터, 값을 미리 갖다놓는 임시 메모리이다. CPU에서 주기억장치, 보조기억장치까지 도달하는 비용은 매우 크고, 물리적으로 거리가 멀다고 할 수 있다. 그런데 캐시의 경우 CPU 바로 옆에 딱 달라붙어있기 때문에 물리적으로도 거리가 매우 짧아 접근 비용이 매우 적다. 따라서 자주 사용되는 값이나, 사용될 예정인 값을 미리 캐시에 적재해놓는다면 참조 시간을 대폭 줄여 성능을 높일 수 있다.

CPU는 어떤 값이 필요할 때 가장 먼저 캐시를 방문하고 만약 캐시에 원하는 값이 있을 경우 이를 사용하는데, 만약 없다면 주기억 장치를 방문한다. 따라서, CPU 가 자주 사용하는 값, 필요로 하는 값 등을 적절히 캐시에 배치해두어야 한다. 즉, 캐시 히트율을 높여야 성능을 높일 수 있다.

 

Cache Hit : CPU가 참조하고자 하는 메모리가 캐시에 존재하고 있을 경우
Cache Miss : CPU가 참조하고자 하는 메모리가 캐시에 존재하지 않는 경우

 

캐시의 내용물들은 자주 갈아끼워질 필요가 있다. 캐시의 용량은 한정적이지만 자주 사용되는 값 혹은 사용될 예정인 값은 시시각각 변하기 때문이다. 막무가내로 내용물을 갈아끼우면 캐시 히트율을 항상 높게 유지하기 어려울 것이고, 성능 악화로 이어질 수 있다. 따라서 캐시 히트율을 높게 유지하는 메모리 교체 알고리즘이 필요하다. Cache 알고리즘 중에 가장 유명한 알고리즘 중 하나는 LRU 알고리즘이다.

 

 

LRU 알고리즘

캐시에 공간이 부족할 때 가장 오랫동안 사용하지 않은 항목을 제거하고, 새로운 데이터를 배치한다.

구현은 보통 LinkedList, Queue, ArrayList 등을 사용한다.

 

 


Reference

 

페이지 교체(page-replacement) 알고리즘

요구 페이징 시스템은 프로세스가 특정 페이지를 요구할 때 해당 페이지를 물리 메모리에 로딩한다.

medium.com

 

[OS] 페이지 교체 알고리즘 - FIFO/LRU/LFU/MFU/NUR

💡 페이지 교체 알고리즘 운영체제는 주기억장치보다 더 큰 용량의 프로그램을 실행하기 위해 프로그램의 일부만 주기억장치에 적재하여 사용한다. 이를 가상메모리 기법이라 한다. 페이징 기

doh-an.tistory.com

 

LRU Cache 이해하기

상당히 유용하게 사용되는 LRU 캐싱 이해하기

velog.io

 

LRU Cache Algorithm 정리

Cache 알고리즘 중에 가장 유명한 알고리즘 중 하나로 LRU 알고리즘 이라는 것이 있다. LRU 알고리즘이란 Least Recently Used Algorithm 의 약자로, 캐시에서 메모리를 다루기 위해 사용되는 알고리즘이다.

jins-dev.tistory.com

 

728x90

'Algorithms > Algorithm' 카테고리의 다른 글

백트래킹 (Backtracking)  (0) 2022.11.24
돋 보 기🔍
728x90

이 문제는 비트 연산(Bitwise Operaiton)을 묻는 문제라고 한다. 2진수로 처리하라는 내용이 힌트이고, OR로 처리하면 된다. if else 풀이를 한 사람이 많았지만 ( 뜨끔 ,, ) 비트 연산을 잘 다룰 수 있는지를 묻고자 하는 의도였다고 한다. 이런 유형을 풀 때는 비트 연산을 기억하자 !.

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

처음 구상한 코드는 다음과 같다. 

 

1. toBinaryString()을 사용해 10진수를 2진수로 변환한다.

2. 변환한 2진수의 길이를 통일한다.

3.   StringBuilder를 이용해 공백 혹은 #을 append 하고, 그 값을 answer에 넣어준다.

 

import java.util.*;

class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        
        for (int i=0; i<n; i++) {
            
            // 1. 10진수를 2진수로 변환한다.
            
            String x = Integer.toBinaryString(arr1[i]);
            String y = Integer.toBinaryString(arr2[i]);
            
            // 2. 변환한 2진수의 길이를 통일한다.
            
            String zero = "";
            if (x.length()<n) {
            	int num = n - x.length();
            	for (int j=0; j<num; j++) {
            		zero = "0" + zero ;
            	}
            	x = zero + x;
            }
            
            zero = "";
            if (y.length()<n) {
            	int num = n - y.length();
            	for (int j=0; j<num; j++) {
            		zero = "0" + zero ;
            	}
            	y = zero + y;
            }
            
            // 3. 두 장의 지도를 겹친다.
            
            StringBuilder sb = new StringBuilder();
            
            for (int j=0; j<n; j++) {
                char a = x.charAt(j);
                char b = y.charAt(j);
                
                if (a == '0' && b == '0') sb.append(" ");
                else sb.append("#");
            }
            
            answer[i] = sb.toString();

        }
        
        return answer;
    }
}

 

 

+ 더 나은 풀이 방법

문제를 다 풀고 다른 코드를 찾아보니

나처럼 arr1과 arr2 안의 숫자를 각각 2진수로 변환해 두 숫자를 합치지 않아도,

비트 논리 연산자 OR (논리합)를 사용하면 더 간단한 코드로 구현할 수 있다.

OR ( | )는 두 비트 중 하나만 1이면 연산 결과는 1이다.

 

변환한 2진수는 문자열의 형식을 설정할 때 이용하는 %s(=String Formatting)을 이용해 길이를 통일한다.

String.format("%" + n + "s", binary) :  binary의 길이보다 숫자 n이 더 작으면 앞에 공백을 추가해준다고 한다.

 

마지막으로 문자열 치환을 해주는 Replace 함수를 사용해 공백 혹은 #으로 바꾸어준다.

코드는 아래와 같다.

import java.util.*;

class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        
        for (int i=0; i<n; i++) {
            
            // 1. 10진수를 2진수로 변환 : 비트 논리 연산자 OR 사용
            
            String binary = Integer.toBinaryString(arr1[i] | arr2[i]);
            binary = String.format("%" + n + "s", binary);
            
            // 2. replace 함수로 문자열을 치환한다.
            
            binary = binary.replace('0', ' ');
            binary = binary.replace('1', '#');        
            answer[i] = binary;
        }
        return answer;
    }
}

 

그런데 실행 결과를 보면 효율은 첫 번째로 푼 코드가 더 좋아보인다 ,,

하지만 !

 

Kakao Tech 블로그에서 문제 해설을 보면 이 문제는 비트 연산(Bitwise Operaiton)을 묻는 문제라고 한다.

2진수로 처리하라는 내용이 힌트이고, OR로 처리하면 된다.

if else 풀이를 한 사람이 많았지만 ( 뜨끔 ,, ) 비트 연산을 잘 다룰 수 있는지를 묻고자 하는 의도였다고 한다.

이런 유형을 풀 때는 비트 연산을 기억하자 !

728x90
돋 보 기🔍
728x90

백트래킹 (Backtracking) 이란?

해를 찾는 도중 해가 아니어서 막히면, 되돌아가서 다시 해를 찾아가는 기법을 말한다.

코딩에서는 반복문의 횟수를 줄일 수 있어 효율적이다.

 

 

일종의 트리 탐색 알고리즘이라고 봐도 된다.

모든 경우의 수를 전부 고려하는 알고리즘 상태공간을 트리로 나타낼 수 있을 때 적합한 방식이다.

 

보통 비선형으로 구성된 자료 구조를 깊이 우선 탐색(Depth First Search, DFS)할 때, 

더 이상 나아갈 수 없는 상황에서 그 이전 단계로 복귀하는 과정이다.

 

깊이 우선 탐색(DFS) VS 백트래킹(Backtracking)

DFS는 가능한 모든 경로를 탐색한다. (완전 탐색 O)

불필요할 것 같은 경로를 사전에 차단하지 않기 때문에 경우의 수를 줄이지 못한다.

 

백트래킹은 모든 경로 중 특정 조건을 만족하는 경로만 탐색한다. (완전 탐색 X)

 

유망성 (promising) VS 가지치기 (pruning)

불필요한 부분을 쳐내고 최대한 올바른 쪽으로 간다는 의미에서 '가지치기'라고도 한다.

가지치기를 얼마나 잘하느냐에 따라 효율성이 결정된다.

유망성을 판단했을 때,

해가 될 가능성이 있는 것은 promising, 유망하지 않은 노드에 가지 않는 것은 pruning ! 

 

주로 문제를 풀 때 DFS 등으로 모든 경우의 수를 탐색하는 과정에서 답이 절대로 될 수 없는 상황을 조건문으로 정의하고, 그러한 상황일 경우에는 탐색을 중지하고 그 이전으로 돌아가서 다시 다른 경우를 탐색하도록 구현한다. 

 

즉, 백트래킹은 최적화 문제결정 문제를 푸는 방법이 되고, 보통 재귀함수로 구현한다.

 

+ 탐색 알고리즘이란 ?

 


Reference

 

알고리즘 기법[전체 탐색] - 백트래킹(Backtracking)

백트래킹(Backtracking) 비선형으로 구성된 자료 구조를 깊이 우선으로 탐색할 때, 더 이상 나아갈 수 없는 상황에서 그 이전 단계로 복귀하는 과정을 말한다. -일반적으로 최적화 문제를 해결할 때

hcr3066.tistory.com

 

알고리즘 - 백트래킹(Backtracking)의 정의 및 예시문제

이번에 살펴볼 개념은 백트래킹에 관한 내용입니다.

chanhuiseok.github.io

 

[Algorithm] 백트래킹(Backtracking)이란? (feat. 예제포함)

안녕하세요 Foma 💻 입니다! 오늘은 프로그래머스 N-Queen 문제를 풀면서 해당 문제가 백트래킹 문제라는 것을 알게 되었는데요. 그래서 백트래킹이 무엇이고 어떻게 구현해서 사용해야 하는지에

fomaios.tistory.com

 

[알고리즘] 백트래킹 Backtracking

백트래킹(Backtracking) 현재 상태에서 가능한 모든 후보군을 따라 들어가며 탐색하는 알고리즘 해(정답)을 찾는 도중 해가 아니어서 막히면, 되돌아가서 다시 해를 찾아가는 기법 완전 탐색X 최적

imyena.tistory.com

 

퇴각검색 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 퇴각검색(영어: backtracking, 한국어: 백트래킹)은 한정 조건을 가진 문제를 풀려는 전략이다. "퇴각검색(backtrack)"이란 용어는 1950년대의 미국 수학자 D. H. 레머가

ko.wikipedia.org

 

728x90

'Algorithms > Algorithm' 카테고리의 다른 글

페이지 교체 알고리즘과 LRU Cache  (0) 2022.12.02
돋 보 기🔍
728x90

Naver Cloud Platform

Naver Cloud PlatForm 에는 정말 다양한 API 서비스가 많다.

그 중에서도 AI Services 에 속한 몇 가지 API를 사용해보았다.

 

Naver Cloud Platform에서 제공해주는 API를 활용해 

SpringBoot에서  SpringMVC 구조로 만들어

Tomcat 서버를 돌려 웹 페이지로 결과를 보았다 !

 

 

 

Object Detection 

이미지 속 사람 및 자동차 등 다양한 객체의 타입과 위치를 감지하여 정보를 제공해준다.

빨간색 박스는 AI가 인식한 객체를 시각적으로 보여주기 위해 Json 데이터와 canvas를 이용해 그린 것이다.

수도리가 강아지라고 잘 인식해준다.

놀라운 건 프리즈비도 잘 인식한다 ! 

97% !

 

ㄴㅁㄱ

 

 

사진 위에 쓰여진 글씨를 보면 알 수 있듯이,

객체의 수와 객체 타입(ex) dog)과 탐지 정확률(ex) 99%)을 제공해준다.

Json 데이터에 정보가 저장되어 있어서 JSON Viewer를 활용해 분석했다.

 

JSON Viewer

Easily view and visualize JSON (and JSON like) data using our JSON Viewer, visualization tools, and online REPL

jsonviewer.arianv.com

복잡한 Json 데이터를 예쁘게 보여준다.

사실 예뻐도 복잡하긴 매한가지다. ^^

 

 

 

 

Pose Estimation

이미지 속의 사람을 감지하고 몇 명이 어떤 포즈를 취하고 있는지에 대한 좌표 정보를 얻을 수 있다.

주요 신체 영역을 인식한 좌표 정보를 제공해주기 때문에 자세 교정을 도와줄 때 사용하기 좋다고 한다.

 

아래 사진은 해외에서 Pose Estimation을 Deep Learning으로 구현한 것이라고 하는데 제법 멋지다.

 

 

 

아래 사진은 Naver Cloud Platform에서 제공해주는 API를 이용해 구현해본 것이다.

역시 Json 데이터와 canvas를 이용했다.

신체 부위를 딱 정확하게 찝어낸다.

놀라운 AI ,,,,,, 

 

신체부위를 점으로 나타내는 것 뿐만 아니라

저 위에 스케이드 타는 사진처럼 좌표와 좌표끼리 이어 선을 만들 수도 있다. 

 

 

 

 

CLOVA Voice

그리고 !

네이버의 얼굴 (?)

CLOVA !

 

CLOVA Voice는 다양하고 자연스러운 목소리를 만들 수 있는 고품질 음성 합성 서비스라고 한다.

 

아래 영상은 질문을 쓰고 대화 버튼을 누르면 !

CLOVA Voice API를 이용해 음성으로 대답해주는 간단한 테스트이다.

 

질문과 대답은 HashMap으로 저장해두었다.

 

 

 

 

CLOVA Chatbot

그런데, 실제로 이런 형태를 만드려면 CLOVA Chatbot 서비스를 사용해야겠다.

CLOVA Chatbot은 마케팅, 고객 응대 등 다양한 서비스에 활용할 수 있는 챗봇을 생성하는 서비스이다.

챗봇은 질문과 대답을 다양한 형태로 여러개 생성할 수 있고, 특히 정규식 표현도 가능해서 훨씬 편리하다.

 

 

 

 

CLOVA OCR, CLOVA Speech Recognition

이미지 속 문자를 추출해 디지털 데이터로 변환해주는 CLOVA OCR,

사람 목소리를 텍스트로 바꿔주는 CLOVA Speech Recognition(CSR)도 사용해봤는데 흥미로웠다.

 

STT(Speech to Text), TTS(Text to Speech)가 가능하다는 점을 이용해

시각 혹은 청각 장애를 겪고 있는 사람들에게 도움이 될 만한 서비스가 많아지는 세상이 올 수 있겠다는 생각이 들었다. 

 

 

 

 

NAVER CLOUD PLATFORM

cloud computing services for corporations, IaaS, PaaS, SaaS, with Global region and Security Technology Certification

www.ncloud.com

 

 

 

 

 


Reference

 

An Overview of Human Pose Estimation with Deep Learning

An introduction to the techniques used in Human Pose Estimation based on Deep Learning.

medium.com

 

728x90

'Log' 카테고리의 다른 글

프랙탈 트리 (Fractal Tree) 🌳  (0) 2023.02.02
백준 골드 달성 일지 v`_`v  (0) 2023.01.25
우분투 (Ubuntu)와 주피터 노트북 (Jupyter notebook)  (0) 2023.01.17
돋 보 기🔍
728x90

덱은 double-ended queue를 줄여서 표현한 것으로, 양방향으로 넣고 뺄 수 있다는 사실에 초점이 맞추어져 지어진 이름이다. 스택과 큐의 특성을 모두 갖는, 둘을 조합한 형태의 선형 자료구조로 이해되고 있다.

목차

덱 (Deque) 이란?

 


덱 (Deque) 이란 ?

양쪽에서 삽입과 삭제가 가능한 자료구조이며 스택과 큐의 연산을 모두 지원한다. 덱은 double-ended queue를 줄여서 표현한 것으로, 양방향으로 넣고 뺄 수 있다는 사실에 초점이 맞추어져 지어진 이름이다. 스택과 큐의 특성을 모두 갖는, 둘을 조합한 형태의 선형 자료구조로 이해되고 있다.

  • appendleft : 왼쪽에서(앞에서) 데이터를 삽입
  • append : 오른쪽에서(뒤에서) 데이터를 삽입
  • popleft : 왼쪽에서 데이터를 꺼내기 (삭제)
  • pop : 오른쪽에서 데이터를 꺼내기 (삭제)

 

 

덱의 분류

  • Scroll : 입력 제한 덱 (Input restricted deque) - 입력은 한쪽에서만 발생, 출력은 양쪽에서 발생
  • Shelf : 출력 제한 덱 (Output restricted deque) - 입력은 양쪽에서 발생, 출력은 한쪽에서만 발생

 

 

덱의 사용

덱은 자주 쓰이지 않는다.

주로 앞, 뒤 모두에서 삽입, 삭제가 이루어질 때 사용한다.

데이터가 가변적일 때 사용한다.

  • 보통 스케줄링에 사용
  • 우선순위 조절 시 사용

 

 

Java class ‘Deque’

// Deque 선언, ArrayDeque 사용
Deque<E> deque = new ArrayDeque<>();

// First : 왼쪽, Last : 오른쪽

// 값 추가 (push) 
deque.offerFirst(추가할 값); //정상적으로 삽입 시 true, 용량 제한 시 false
deque.offerLast(추가할 값); 

deque.addFirst(추가할 값); // 용량 제한 시 예외(Exception) 발생 //push()와 동일
deque.addLast(추가할 값); //add()와 동일

// 값 꺼내기 (pop)
deque.pollFirst(); // 덱이 비어있으면 null // poll()과 동일
deque.pollLast();

deque.removeFirst(); // 덱이 비어있으면 예외 발생 // remove(), pop()과 동일 
deque.removeLast();

// 맨 앞과 맨 뒤의 값 출력
deque.peekFirst(); // 덱이 비어있으면 null //peek()와 동일
deque.peekLast();

deque.getFirst(); // 덱이 비어있으면 예외 발생
deque.getLast();

// 크기 구하기
deque.size();

// 비어있는지 확인 후 boolean 타입으로 반환
deque.isEmpty();

// 검색 후 삭제
deque.removeFirstOccurrence(제거할 값); // 왼쪽(앞)에서부터 탐색
deque.remove(제거할 값); // first와 동일
deque.removeLastOccurrence(제거할 값); // 오른쪽(뒤)에서부터 탐색

// 값이 있는지 확인
deque.contain(확인할 값);

// 순회 (Iterator)
deque.iterator(); // iterator로 변환
deque.descendingIterator(); // 역순 iterator 변환

 

 

장단점

장점 

  • 크기가 가변적이다.
  • 데이터 삽입, 삭제가 빠르다.
  • 원하는 데이터에 바로 접근이 가능하다.

단점

  • 구현이 어렵다.
  • 중간 데이터의 삽입, 삭제가 어렵다.

 

 

시간 복잡도 (Time complexity)

  • Insertion O(1)
  • Deletion O(1)
  • Search O(1)
728x90

'CS > Data Structure' 카테고리의 다른 글

트리 (Tree)  (0) 2022.12.15
큐 (Queue)  (0) 2022.07.25
스택 (Stack)  (0) 2022.07.23
돋 보 기🔍
728x90

큐는 스택과 함께 가장 많이 볼 수 있는 선형 자료구조이다. 스택과 반대로 선입선출이다. 즉, FIFO(First in First Out) 혹은 LILO(Last In Last Out)구조이다. Queue는 사전적으로 ‘줄을 서서 기다리다’라는 의미를 가진다. 매표소에서 먼저 줄을 선 사람이 먼저 표를 사는 것과 같은 논리이다. 큐의 데이터는 맨 뒤로만 들어와서 맨 앞으로만 나갈 수 있다.

목차

큐 (Queue) 란 ?

 

 


큐 (Queue) 란?

큐는 스택과 함께 가장 많이 볼 수 있는 선형 자료구조이다. 스택과 반대로 선입선출이다. 즉, FIFO(First in First Out) 혹은 LILO(Last In Last Out)구조이다. Queue는 사전적으로 ‘줄을 서서 기다리다’라는 의미를 가진다. 매표소에서 먼저 줄을 선 사람이 먼저 표를 사는 것과 같은 논리이다. 큐의 데이터는 맨 뒤로만 들어와서 맨 앞으로만 나갈 수 있다.

 

Enqueue와 Dequeue

  • Enqueue : 큐 맨 뒤에 데이터 추가
  • Dequeue : 큐 맨 앞의 데이터 삭제
  • peek : front에 위치한 데이터 조회
  • front : 큐 맨 앞의 위치(인덱스)
  • rear : 큐 맨 뒤의 위치(인덱스)

 

큐의 사용

데이터가 입력된 시간 순서대로 처리해야 할 필요가 있는 상황에 사용한다.

보통 컴퓨터 버퍼에서 주로 사용한다.

동시다발적으로 입력이 들어오면 대기열을 만들어 순차적으로 처리하는 것이다.

다음은 큐를 사용하는 사례이다.

  • 프린트 출력 처리
  • 프로세스 관리
  • CPU 스케줄링, 디스크 스케줄링
  • 그래프의 넓이 우선 탐색 (BFS)에서 사용
  • 서로 다른 스레드 혹은 프로세스 사이에서 자료를 주고 받을 때 자료를 일시적으로 저장 (비동기 전송) (ex) IO 버퍼)

 

Overflow와 Underflow

  • Queue Overflow : 가득 찬 큐에 데이터를 추가하려고 할 때
  • Queue Underflow : 빈 큐에서 데이터를 꺼내려고(삭제) 할 때

 

Java class ‘Queue’

// Queue 선언, Linkedlist 사용
Queue<E> queue = new LinkedList<>();

// 값 추가
queue.add(추가할 값); // 삽입 성공 시 true, 여유 공간이 없어 삽입 실패 시 IllegalStateException 발생
queue.offer(추가할 값);

// 값 꺼내기 (삭제)
queue.poll(); // 맨 앞의 값 반환 후 제거, 큐가 비어있으면 null 반환
queue.remove(); // 맨 앞의 값 제거
queue.clear(); // 초기화

// 맨 앞의 값 출력
queue.peek();

// 모든 값 출력 (Iterator 클래스 사용)
Iterater iter = queue.iterator();
while (iter.hasNext()) {
	System.out.println(iter.next());
}

// 크기 구하기
queue.size();

// 비어있는지 확인 후 boolean 타입으로 반환
queue.isEmpty();

 

큐 구현 방법

스택과 마찬가지로 배열 혹은 연결리스트를 이용하여 구현할 수 있다.

 

큐 종류

1. 선형 큐 (Linear Queue)

기본적인 큐의 형태로써 막대 모양으로 된 큐이다.

 

선형 큐는 문제점이 있다.

선형 큐에서 삽입(Enqueue), 삭제(Dequeue)를 계속 반복하다 보면 Rear가 맨 마지막 인덱스 ‘5’를 가리키고, 앞에는 비어 있을 수 있지만 이를 꽉 찼다고 인식한다. 이는 데이터 삭제 시 한 칸 앞으로 이동하지 않기 때문이다.

  • 선형 큐 문제점
    • 배열 구현 시 크기가 제한되어 있다.
    • 빈 공간을 사용하려면 모든 자료를 꺼내거나 자료를 한 칸씩 옮겨야 한다. (지연시간 발생)
    • Enqueue, Dequeue 작업이 계속적으로 일어나면 큐가 비어있어도 데이터 추가가 불가능하다. (Overflow 발생)

 

2. 원형 큐 (Circular Queue)

선형 큐의 문제점을 보완한 것이다. 원형 큐는 1차원 배열 형태의 큐를 원형으로 구성하여 배열의 처음과 끝을 연결한다. 환형 큐라고도 한다. 데이터 추가 시 Rear가 한 칸 움직이고, 데이터 삭제 시 Front가 한 칸 움직인다.

 

시간 복잡도 (Time complexity)

  • Insertion O(1)
  • Deletion O(1)
  • Search O(n)
728x90

'CS > Data Structure' 카테고리의 다른 글

트리 (Tree)  (0) 2022.12.15
덱 (Deque)  (0) 2022.07.28
스택 (Stack)  (0) 2022.07.23
돋 보 기🔍
728x90

물건을 쌓아 올리듯이 데이터를 쌓는 자료구조로, 한 쪽 끝에서만 자료를 넣거나 뺄 수 있는 선형 자료구조(Linear Data Structur)이다. ‘Pushdown list’라 부르기도 한다.

목차

스택 (Stack) 이란?

 

 


스택 (Stack) 이란 ?

물건을 쌓아 올리듯이 데이터를 쌓는 자료구조로,

한 쪽 끝에서만 자료를 넣거나 뺄 수 있는 선형 자료구조(Linear Data Structur)이다.

‘Pushdown list’라 부르기도 한다.

 

자료를 넣는 것을 Push 라고 하고, 꺼내는 것을 Pop 이라고 한다.

꺼내지는 자료는 가장 최근에 Push한 자료부터 나오게 된다.

평소에 사용하는 ‘뒤로가기’를 생각하면 이해가 쉽다.

뒤로가기를 누르면 가장 최근에 방문한 사이트를 보여주는 것 말이다.

제일 마지막에 넣은 값이 먼저 나오는 것을 LIFO(Last in First out) 혹은 FILO(First in Last out)구조라고 한다.

 

Push

데이터를 스택에 넣는다.

step 1 : 스택이 가득 찼는지 확인

step 2 : 스택이 가득 차면 오류 발생하고 종료

step 3 : 스택이 가득 차지 않으면 Top 증가

step 4 : Top이 가리키는 스택 위치에 데이터 추가

 

Pop

데이터를 스택에서 꺼내온다. 즉, 제거한다.

step 1 : 스택이 비어 있는지 확인

step 2 : 스택이 비어 있으면 오류 발생하고 종료

step 3 : 스택이 비어 있지 않으면 Top이 가리키는 데이터 제거

step 4 : Top 값 감소

step 5 : 성공을 반환

 

스택의 사용

스택은 직전의 데이터를 빠르게 가져올 수 있고, 균형성 검사도 가능하다.

다음은 스택을 사용하는 사례이다.

  • 자바 Stack 메모리
  • 재귀 알고리즘
  • Backtracking
  • 웹 브라우저 방문 기록, 뒤로 가기
  • 실행 취소 (undo)
  • 역순 문자열 만들기
  • 그래프의 깊이 우선 탐색 (DFS)

 

Overflow와 Underflow

Stack Overflow : 스택이 완전히 꽉 찼을 때

Stack Underflow : 스택이 완전히 비어 있을 때

 

Java class ‘ Stack ’

// Stack 선언
Stack<E> stack = new Stack<>();

// 값 추가
stack.push(추가할 값);

// 값 꺼내기 (삭제)
stack.pop();

// 전체 값 삭제 (초기화)
stack.clear(); 

// 가장 상단의 값 출력
stack.peek();

// 비어있는지 check (비어있으면 true)
stack.empty();

// 1이 있는지 check (있으면 true)
stack.contains(1);

 

스택 구현 방법

1. 배열 사용

  • 장점 : 구현하기 쉽다.
  • 단점 : 크기가 동적이 아니다. 런타임 시 필요에 따라 늘어나거나 줄어들지 않는다.

 

2. 연결 리스트 사용

  • 장점 : 크기가 동적이다. 필요에 따라 크기가 확장되거나 축소될 수 있다.
  • 단점 : 포인터를 위한 추가 메모리 공간이 필요하다.

 

시간 복잡도 (Time complexity)

  • Insertion O(1)
  • Deletion O(1)
  • Search O(n)

 

삽입(push), 삭제(pop)는 항상 Top에서만 일어나기 때문에 O(1) 시간이 걸린다.

하지만 특정 데이터를 찾을 때에는 특정 데이터를 찾을 때까지 수행하기 때문에 O(n)이다.

728x90

'CS > Data Structure' 카테고리의 다른 글

트리 (Tree)  (0) 2022.12.15
덱 (Deque)  (0) 2022.07.28
큐 (Queue)  (0) 2022.07.25
돋 보 기🔍
728x90

End point 간 신뢰성 있고, 효율적인 데이터 전송을 담당하는 계층이다. 프로토콜(TCP, UDP)로 구성되어 흐름 제어, 혼잡 제어, 오류 제어 등을 담당한다. 순차 번호 기반의 오류  제어 방식을 사용한다.

목차

  1. 전송계층
  2. TCP  
  3. UDP

 


전송계층 (Transport Layer)

End point 간 신뢰성 있고, 효율적인 데이터 전송을 담당하는 계층이다. 프로토콜(TCP, UDP)로 구성되어 흐름 제어, 혼잡 제어, 오류 제어 등을 담당한다. 순차 번호 기반의 오류  제어 방식을 사용한다.

 

전송계층이 없다면?

  • 데이터의 순차 전송이 원활 x
  • Flow (흐름 문제) : 송수신자 간의 데이터 처리 속도 차이
  • Congestion (혼잡 문제) : 네트워크의 데이터 처리 속도 

 


TCP (Transmission Control Protocol)

  • 클라이언트와 서버가 연결된 상태에서 신뢰성 있는 데이터 통신을 가능하게 해주는 프로토콜
  • 일반적이고 대중적인 방식
  • 신뢰성이 높고 속도가 느림
  • 연결 지향 : 상대가 데이터를 받았는지 확인하면서 통신하는 방식
  • 데이터 순차 전송을 보장
  • 패킷의 손실, 중복, 순서변경이 없음을 보장
  • 흐름 제어, 혼잡 제어, 오류 감지
    • Flow Control (흐름 제어): 송신 및 수신 속도를 일치시킴
    • Congestion Control (혼잡 제어): 네트워크 혼잡시 데이터 전송 속도를 강제로 줄임
    • Error Detection (오류 감지)

 

Segment : TCP 프로토콜의 PDU

* PDU : Protocol Data Unit 각 계층에서 헤더와 데이터를 합친 부분을 말한다. 계층마다 부르는 이름이 다르고, 3계층인 네트워크 계층 PDU는 패킷(Packet)이라고 부른다.

전송 계층에서는 세션 계층에서 전달된 데이터를 받아 실질적인 전송을 위해 일정 크기로 나눈다. 이렇게 나누어진 데이터에는 출발지 포트(보낸 이), 목적지 포트(받는 이), 순서 번호, 오류 검출 등이 헤더로 붙게 되는데 이것을 세그먼트라고 부른다. 세그먼트는 전송 계층의 TCP 프로토클이 응용 계층의 데이터 단위인 메시지를 받아 작은 조각으로 분할한 데이터 단위이다. 즉, TCP 프로토콜에 따라 분할된 데이터에 TCP 헤더가 붙어 캡슐화된 전송 계층의 패킷이 세그먼트이다. 이 세그먼트는 인터넷 계층으로 전송된다.

 

TCP 헤더

출처 : https://en.wikipedia.org/wiki/Transmission_Control_Protocol

SYN : TCP가 Connection을 연결할 때 쓰는 플래그 비트

FIN : Connecion 연결 후 끊어낼 때 쓰는 플래그 비트

ACK : 데이터 전송을 받는 사람이 다시 전송할 때 제어하는 플래그 비트



 

TCP의 3 way-handshake (Connection 연결)

[STEP 1]

SYN 비트를 1로 설정해 패킷 송신

A클라이언트는 B서버에 접속을 요청하는 SYN 패킷을 보낸다. 이때 A클라이언트는 SYN 을 보내고 SYN/ACK 응답을 기다리는SYN_SENT 상태가 되는 것이다.

 

[STEP 2]  

SYN, ACK 비트를 1로 설정해 패킷 송신

B서버는 SYN요청을 받고 A클라이언트에게 요청을 수락한다는 ACK 와 SYN flag 가 설정된 패킷을 발송하고 A가 다시 ACK으로 응답하기를 기다린다. 이때 B서버는 SYN_RECEIVED 상태가 된다.

 

[STEP 3]

ACK 비트를 1로 설정해 패킷 송신

A클라이언트는 B서버에게 ACK을 보내고 이후로부터는 연결이 이루어지고 데이터가 오가게 되는것이다. 이때의 B서버 상태가 ESTABLISHED 이다. 

 

 

 

TCP의 데이터 전송 방식

1. Client가 패킷 송신

2. Server에서 ACK 송신

3. ACK를 수신하지 못하면 재전송

 

 

TCP의 4 way-handshake (Connection close)

[STEP 1]

데이터를 전부 송신한 Client가 FIN 송신

클라이언트가 연결을 종료하겠다는 FIN플래그를 전송한다.


[STEP 2] 

Server가 ACK 송신, Server에서 남은 패킷 송신 (일정 시간 대기)

서버는 일단 확인메시지를 보내고 자신의 통신이 끝날때까지 기다리는데 이 상태가 TIME_WAIT상태다. 

 

[STEP 3]

Server가 FIN 송신

서버가 통신이 끝났으면 연결이 종료되었다고 클라이언트에게 FIN플래그를 전송한다. 

 

[STEP 4]

Client가 ACK 송신

클라이언트는 확인했다는 메시지를 보낸다.

 

만약 Server에서 FIN을 전송하기 전에 전송한 패킷이 Routing 지연이나 패킷 유실로 인한 재전송 등으로 인해 FIN패킷보다 늦게 도착하는 상황"이 발생한다면 어떻게 될까? 

 

Client에서 세션을 종료시킨 후 뒤늦게 도착하는 패킷이 있다면 이 패킷은 Drop되고 데이터는 유실될 것이다. 

이러한 현상에 대비하여 Client는 Server로부터 FIN을 수신하더라도 일정시간(디폴트 240초) 동안 세션을 남겨놓고 잉여 패킷을 기다리는 과정을 거치게 되는데 이 과정을 "TIME_WAIT" 라고 한다.

 

 

 

TCP 상태도

 

TCP의 문제점

  • 매번 Connection을 연결해서 시간 손실 발생 (3 way-handshake)
  • 패킷을 조금만 손실해도 재전송

 


UDP (User Datagram Protocol)

  • TCP보다 신뢰성이 낮지만 전송 속도가 빠른 프로토콜
  • 신뢰성이나 정확성보다는 효율을 중시
  • 비연결 지향: 상대가 데이터를 받았는지 확인하지 않고 일방적으로 통신하는 방식
  • 데이터 순서를 보장 x
  • Error Detection (오류 감지)만 있음
  • 비교적 데이터의 신뢰성이 중요하지 않고 빠른 처리가 필요할 때 사용 (ex) 실시간 스트리밍)

 

User Datagram : UDP 프로토콜의 PDU 

UDP Header

출처 : https://en.wikipedia.org/wiki/User_Datagram_Protocol

TCP Header처럼 복잡하지가 않다. TCP처럼 전송을 위해 포트 번호가 있고, 에러 검출을 위한 Checksum이 있다.

 

 

 

UDP의 데이터 전송 방식

1. Client가 패킷 송신

Connection이 없기 때문에 확인도 안하고 그저  전송하기 위해 열어두기만 한다.

 

 

 

UDP의 문제점

  • 데이터의 신뢰성이 없다.
  • 의미있는 서버를 구축하기위해서는 일일이 패킷을 관리해주어야 한다.

<출처 및 참고자료>

 

Network | 전송 계층 (TCP, UDP)

OSI_Model종단 간(End-To-End) 통신을 다루는 계층으로 종단 간 신뢰성 있고 효율적인 데이터를 전송한다.상위 계층들이 데이터 전달의 유효성이나 효율성을 생각하지 않도록 해준다.프로토콜(TCP, UDP)

velog.io

 

[ 네트워크 쉽게 이해하기 22편 ] TCP 3 Way-Handshake & 4 Way-Handshake

우선  TCP의 3-way Handshaking 에 대하여 알아보겠습니다. * TCP 3-way Handshake 란? TCP는 장치들 사이에 논리적인 접속을 성립(establish)하기 위하여 three-way handshake를 사용한다. TCP 3 Way Handshake..

mindnet.tistory.com

 

쉽게 이해하는 네트워크 17. TCP 프로토콜의 기능 및 특징 - 패킷 분할과 연결형 통신

TCP 프로토콜의 기능, 특징 - 세그먼트, 연결형 통신 TCP 프로토콜의 기능과 특징 전송 계층의 대표적인 프로토콜인 TCP는 신뢰할 수 있고 정확한 데이터를 전달하기 위해 연결형 통신을 사용하는

better-together.tistory.com

 

TCP의 헤더에는 어떤 정보들이 담겨있는걸까?

저번에 HTTP/3는 왜 UDP를 선택한 것일까? 포스팅을 진행하며 TCP에 대해 간단한 언급을 했었지만, 해당 포스팅에서는 기존의 HTTP에서 사용하던 TCP에 어떤 문제가 있었는지에 집중해서 이야기했었

evan-moon.github.io

https://en.wikipedia.org/wiki/TransmissionControlProtocol

 

728x90
돋 보 기🔍

+ Recent posts