๋ณธ ๋ด์ฉ์ ์ถ์ฒ๋ 262๊ฐ์ง ๋ฌธ์ ๋ก ์ ๋ณตํ๋ ์ฝ๋ฉ ์ธํฐ๋ทฐ in Java์ ์์ผ๋ฉฐ, ์ถ๊ฐํ ๋ด์ฉ์ด ์์ ์ ์์ต๋๋ค.
์ถ์ฒ ์์คํ ?
- ์ธํฐ๋ท์ด ๋ฐ์ ๋จ์ ๋ฐ๋ผ ์์ดํ ๊ตฌ๋งค ๋ฐ ์ ํธ์ ๋ํ ์ฌ์ฉ์์ ํผ๋๋ฐฑ์ ์ป๊ธฐ ์ฌ์์ก๊ณ , ์ด๋ฌํ ํผ๋๋ฐฑ์ ๋ฐํ์ผ๋ก ๊ณผ๊ฑฐ์ ์ฌ์ฉ์ - ์์ดํ ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํด ์์ดํ ์ ์ถ์ฒํ๋ ๊ฒ์ด ์ถ์ฒ ์์คํ ์ ๊ธฐ๋ณธ์ ์์ด๋์ด.
- ์ฆ,
User
์ ์ ํธItem
์ ์์ธกํ๋ ์์คํ .
์ถ์ฒ ์์คํ ์ ๊ตฌ์กฐ
- ์ ์ฒด ๊ตฌ์กฐ๋ "ํ๋ณด๋ฅผ ์์ฑํ๋ ๋จ๊ณ"์ "๋ญํน์ ๋งค๊ธฐ๋ ๋จ๊ณ"๋ก ๊ตฌ๋ถ
- ํ๋ณด๋ฅผ ์์ฑํ๋ ๋จ๊ณ
a. ์๋ฐฑ๋ง ๊ฐ ์์ดํ ์ค ์ฌ์ฉ์์ ํ๋ ๊ธฐ๋ก ๊ธฐ๋ฐ์ผ๋ก ํ๋ณด๊ฐ ๋ ์์ดํ ๋ค์ ์ ์ ํ๋ ๋จ๊ณ
b. ๋์ ์ ๋ฐ๋๋ก ์ฌ์ฉ์์ ๊ด๋ จ์ด ์๊ณ , ํ์ ํํฐ๋ง์ ํตํด์๋ง ๊ด๋ฒ์ํ ๊ฐ์ธํ๋ฅผ ์ ๊ณต
c. list์์ ์ต์์ list๋ฅผ ์ ์ํ๊ธฐ ์ํด์๋ recall์ด ๋์ ํ๋ณด ๊ฐ ์๋์ ์ค์์ฑ ๊ตฌ๋ถ์ ์ํด ์ธ๋ฐํ ์์ค์ ํํ์ด ํ์
- ๋ญํน์ ๋งค๊ธฐ๋ ๋จ๊ณ
a. ์์ดํ ๊ณผ ์ฌ์ฉ์๋ฅผ ์ค๋ช ํ๋ Feature๋ฅผ ์ฌ์ฉํด ์ํ๋ ๋ชฉ์ ํจ์์ ๋ฐ๋ผ ๊ฐ ์์ดํ ์ ์ ์๋ฅผ ํ ๋นํด ๊ฐ์ฅ ๋์ ์ ์๋ฅผ ๋ฐ์ ์์ดํ ์ด ์ ์์ ๋ฐ๋ผ ์์๊ฐ ๋งค๊ฒจ์ ธ ์ฌ์ฉ์์๊ฒ ํ์
ํ์ ํํฐ๋ง(Collaborative Filtering)
๋ ๋ช ์ ์ฌ์ฉ์๊ฐ ๋น์ทํ ๊ด์ฌ์ฌ๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด, ํ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐํ์ผ๋ก ๋ค๋ฅธ ์ฌ์ฉ์์๊ฒ ์ถ์ฒํ๋ ๋ฐฉ์
์ฌ์ฉ์ ๊ฐ์ ์ ํธ๋๋ฅผ ์๋ก ๊ณ ๋ คํด ๋ง์ ์ ํ์ฌํญ๋ค๋ก๋ถํฐ ์์ดํ ์ ๊ฑธ๋ฌ๋ด๊ฑฐ๋ ์ ํ
Memory-Based methods
Model - based methods
ํ์
ํํฐ๋ง์ ํ๊ณ์
์ฝ๋ ์คํํธ
๊ณ์ฐ ํจ์จ ์ ํ
๋กฑํ
์ผ
์ปจํ ์ธ ๊ธฐ๋ฐ ํํฐ๋ง(Content based Filtering)
์ฌ์ฉ์๊ฐ ๊ณผ๊ฑฐ์ ๊ฒฝํํ๋ ์์ดํ ์ค ๋น์ทํ ์์ดํ ์ ํ์ฌ ์์ ์์ ์ถ์ฒํ๋ ๊ฒ
์ ๋ณด๋ฅผ ์ฐพ๋ ๊ณผ์ ๊ณผ ๊ณผ๊ฑฐ ์ ๋ณด๋ฅผ ํ์ฉํด ์ ์ ์ ์ฑํฅ์ ๋ฐฐ์ฐ๋ ๋ฌธ์ ์.
๋ฐ์ดํฐ ํ๋ ํ, ์ปจํ ์ธ ๋ถ์์์ ๋น์ ํ ๋ฐ์ดํฐ๋ก๋ถํฐ ๊ด๋ จ ์๋ ์ ๋ณด๋ฅผ ์ป๋ ์์ ์ด ํ์
๋ค์ํ ํญ๋ชฉ ์ถ์ฒ์ ๋ํ ์ด๋ ค์
Hint : ๊ธฐ์ ์ ํต์ฌ์ ๊ด๋ จ ์๋ ๊ธฐ์ฌ์ ๋ฆฌ์คํธ๋ฅผ ์์๋ด๋ ๊ฒ
๋ฌธ์ ๋ถ์ ์, ์ฌ๋ฌ ๊ฐ์ง ๋ฌธ์ ๋ฅผ ์ง๋ฉดํ๊ฒ ๋ ๊ฒ.
์น ์๋ฒ ๋ก๊ทธ ํ์ผ์ ์ฟ ๊ธฐ์ ํ์์คํฌํ๋ฅผ ์ดํด๋ณด๊ธฐ
์ฅ๋ฅด ๊ธฐ๋ฐ ์ถ์ฒ ์์คํ
1๏ธโฃ[SpringBoot] ์ฅ๋ฅด๊ธฐ๋ฐ ๊ฐ๋จํ ์ํ ์ถ์ฒ API ์ค๊ณํ๊ธฐ
2๏ธโฃ [ํ ์ด ํ๋ก์ ํธ] ์ํ ์ถ์ฒ
3๏ธโฃ ์คํ๋ง๋ถํธ์ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ด์ฉํ ์ถ์ฒ ์์ง ๊ตฌํ
4๏ธโฃ ํ์ ํํฐ๋ง
์ค์๊ฐ ์ถ์ฒ ์์คํ
1๏ธโฃ ์ค์๊ฐ ์ถ์ฒ์์คํ ๊ตฌํ๋ฐฉ๋ฒ ๋ฌธ์
์ถ์ฒ
์ฝ๋ ๋ฐ ๋ด์ฉ์ ๋ํ ์ถ์ฒ๋ ์์ 1, 2๋ฒ ๋งํฌ์ ์์ต๋๋ค!
์๋๋ฆฌ์ค
- MovieLense ๋ฐ์ดํฐ ํ์ฉ -> ๋ฐ์ดํฐ๋ฅผ MySQL์ ๋ชจ๋ ์ ์ฅ
- ์ฌ์ฉ์์๊ฒ ์ ์ฒด ์ํ ๋ฆฌ์คํธ ๋๊ธฐ๊ธฐ
- ์ฌ์ฉ์๋ ์๋ฒ์ 10๊ฐ์ ์ํ๋ฅผ ์ ํํด ๋ค์ ์ ์ก
- ์ฌ์ฉ์๊ฐ ์ ํํ ์ํ์์ ์ฅ๋ฅด๋ง ์ถ์ถ(๊ฐ์ฅ ๋ง์ด ์ ํ๋ ์ฅ๋ฅด 2๊ฐ ์ ์ )
- ์ ์ฒด ์ํ ๋ฆฌ์คํธ ์ค ์ ํ๋ ์ฅ๋ฅด 2๊ฐ๊ฐ ํฌํจ๋ ์ํ๋ค์ ์ถ์ฒ ์ํ๋ก ๋ฐํ
์ํฐํฐ ์ค์
๐ MovieEntity
๐ GenresEntity
์ปจํธ๋กค๋ฌ
๐ dummyController
//์ฒซ๋ฒ์งธ ๋ผ์ธ ์ ์ธ -> skipFirstLine ๋ณ์ ์ฌ์ฉ
movieRepo.save(Movies.builder()
.id(movieId).tId(MovieIdToTid.get(movieId))
.title(title.toString())
.genres(Arrays.stream(genre)
.map(genreService::findOrCreateNew)
.collect(Collectors.toSet()))
.build());
//findOrCreateNew ๋ฉ์๋ -> ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํด๋น ์ด๋ฆ์ ์ฅ๋ฅด๊ฐ ์กด์ฌํ๋ฉด ๊ทธ ์ฅ๋ฅด ์ฌ์ฉ or ์๋ค๋ฉด ์๋ก ์ ์ฅ
package com._chanho.movie_recommendation.genre;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class GenreService {
private final GenresRepo genresRepo;
public Genres findOrCreateNew(String name) {
return genresRepo.findByName(name).orElseGet(
() -> genresRepo.save(new Genres(name))
);
}
}
//movieId -> tmdbId ๋ณํ์ ์ํ ๋น ๋ฑ๋ก
package com._chanho.movie_recommendation.api;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
@Configuration
@RequiredArgsConstructor
public class AppConfig {
@Bean
public Map<Long, Long> MovieIdToTid() {
Map<Long, Long> movieIdToTid = new HashMap<>();
File csv = new File("{your_path}\\links.csv");
BufferedReader br = null;
try {
br = new BufferedReader(new BufferedReader(new FileReader(csv)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
String line = "";
boolean skipFirstLine = true;
while (true) {
try {
assert br != null;
if ((line = br.readLine()) == null) break;
} catch (IOException e) {
e.printStackTrace();
}
if (skipFirstLine) {
skipFirstLine = false;
continue;
}
String[] token = line.split(",");
if(token.length > 2) {
Long movieId = Long.parseLong(token[0]);
Long tId = Long.parseLong(token[2]);
movieIdToTid.put(movieId, tId);
}
}
return movieIdToTid;
}
}
๐ MovieController
์ ์ฒด ์ํ๋ฅผ ๋ฐํํด์ฃผ๋ ์ปจํธ๋กค๋ฌ ์์ฑ
Pagenation์ ํตํด 100๊ฐ์ฉ ์๋ฅด๊ธฐ
package com._chanho.movie_recommendation.movie;
import com._chanho.movie_recommendation.genre.Genres;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.persistence.criteria.CriteriaBuilder;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/movie")
public class MovieController {
private final MovieRepo movieRepo;
private final MovieService movieService;
@GetMapping("/movies")
public ResponseEntity retrieveMovies(@PageableDefault(size = 100) Pageable pageable) {
return movieService.retrieveMovies(pageable);
}
@PostMapping("/recommendation")
public List<Movies> getRecommendation(@RequestBody RecommendationDto recommendationDto) {
HashMap<Genres, Integer> pickedGenres = movieService.getPickedGenres(recommendationDto);
HashMap<Genres, Integer> pickedGenresWithSort = movieService.sortByValue(pickedGenres);
Set<Genres> selectBestInKeys = movieService.selectKeyInMap(pickedGenresWithSort);
return movieRepo.findByGenres(selectBestInKeys, recommendationDto);
}
}
์๋น์ค
๐ MovieService
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class MovieService {
private final MovieRepo movieRepo;
private final GenresRepo genresRepo;
public ResponseEntity retrieveMovies(Pageable pageable) {
Page<Movies> moviesPage = movieRepo.findAll(pageable);
return new ResponseEntity<>(moviesPage, HttpStatus.OK);
}
public HashMap<Genres, Integer> sortByValue(HashMap<Genres, Integer> raw) {
return raw.entrySet()
.stream()
.sorted((i1, i2) -> i1.getValue().compareTo(i2.getValue()))
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(e1, e2) -> e2, LinkedHashMap::new
));
}
public HashMap<Genres, Integer> getPickedGenres(RecommendationDto recommendationDto) {
HashMap<Genres, Integer> pickedGenres = new HashMap<>();
recommendationDto.getPickedMovies().forEach(
movieData -> {
Movies movie = movieRepo.findById(movieData.getMovieId()).orElseThrow(
() -> new IllegalStateException("Cannot find Movies with given id: " + movieData.getMovieId().toString()));
Set<Genres> genresList = movie.getGenres();
for(Genres g : genresList) {
Integer count = pickedGenres.getOrDefault(g, 0);
pickedGenres.put(g, count);
}
}
);
return pickedGenres;
}
public Set<Genres> selectKeyInMap(HashMap<Genres, Integer> pickedGenresWithSort) {
Iterator<Genres> keys = pickedGenresWithSort.keySet().iterator();
Set<Genres> selectBestInKeys = new HashSet<>();
int count = 0;
while(keys.hasNext() && count < 2) {
Genres genres = keys.next();
selectBestInKeys.add(genres);
count++;
}
return selectBestInKeys;
}
}
DTO
๐ RecommendationDTO
package com._chanho.movie_recommendation.movie;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data @Builder
@NoArgsConstructor @AllArgsConstructor
public class RecommendationDto {
private Long userId;
private List<MovieData> pickedMovies;
}
@Data @Builder
class MovieData{
private Long tId;
private Long movieId;
private Double rating;
}
Repository
QueryDSL ์ ์ฉ
2๊ฐ์ Predacate ๋ง๋ค๊ธฐ
Genres table๊ณผ left join ํด์ fetchํ๊ธฐ
๐ MovieRepo
package com._chanho.movie_recommendation.movie;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import javax.transaction.Transactional;
@Repository
public interface MovieRepo extends JpaRepository<Movies, Long>, MovieRepoExtension {
@EntityGraph(value = "Movies.withGenres", type= EntityGraph.EntityGraphType.FETCH)
Page<Movies> findAll(Pageable pageable);
}
๐ MovieRepoExtension
package com._chanho.movie_recommendation.movie;
import com._chanho.movie_recommendation.genre.Genres;
import java.util.List;
import java.util.Set;
public interface MovieRepoExtension {
List<Movies> findByGenres(Set<Genres> genres, RecommendationDto recommendationDto);
}
๐ MovieRepoExtensionImpl
package com._chanho.movie_recommendation.movie;
import com._chanho.movie_recommendation.genre.Genres;
import com._chanho.movie_recommendation.genre.QGenres;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.JPQLQuery;
import org.springframework.data.jpa.repository.support.QuerydslRepositorySupport;
import java.util.List;
import java.util.Set;
public class MovieRepoExtensionImpl extends QuerydslRepositorySupport implements MovieRepoExtension {
public MovieRepoExtensionImpl() {
super(Movies.class);
}
@Override
public List<Movies> findByGenres(Set<Genres> genres, RecommendationDto recommendationDto) {
com._chanho.movie_recommendation.movie.QMovies movies
= com._chanho.movie_recommendation.movie.QMovies.movies;
BooleanBuilder containGenres = new BooleanBuilder();
genres.forEach(genre -> {
containGenres.and(movies.genres.contains(genre));
});
BooleanBuilder notInRecommendation = new BooleanBuilder();
recommendationDto.getPickedMovies().forEach(movieData -> {
notInRecommendation.and(movies.id.notIn(movieData.getMovieId()));
});
JPQLQuery<Movies> query = from(movies)
.where(containGenres)
.where(notInRecommendation)
.leftJoin(movies.genres, QGenres.genres).fetchJoin()
.distinct().limit(10);
return query.fetch();
}
}
๐ ์คํ๋ง๋ถํธ์ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ์ ์ด์ฉํ ์ถ์ฒ ์์ง ๊ตฌํํ๊ธฐ
์ฝ๋ ๋ฐ ๋ด์ฉ์ ๋ํ ์ถ์ฒ๋ ์์ 3๋ฒ ๋งํฌ์ ์์ต๋๋ค!
์ถ์ฒ ์์ง?
- ์ฌ์ฉ์์๊ฒ ๋ง์ถคํ ์ถ์ฒ์ ์ ๊ณตํ๊ธฐ ์ํด ๋ค์ํ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ฐ์ดํฐ ๋ถ์ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ ์์คํ
๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ์ค๋น
๋ฐ์ดํฐ ์ค๋น
CREATE TABLE user (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100) UNIQUE
);
CREATE TABLE product (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
category VARCHAR(100)
);
CREATE TABLE review (
id SERIAL PRIMARY KEY,
user_id BIGINT REFERENCES user(id),
product_id BIGINT REFERENCES product(id),
rating INT,
review_text TEXT
);
๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ์ ํ
# 1. ๋ชจ๋ธ ํ์ต
from surprise import Dataset, Reader, SVD
from surprise.model_selection import train_test_split
from surprise import accuracy
# ๋ฐ์ดํฐ ๋ก๋ฉ
reader = Reader(rating_scale=(1, 5))
data = Dataset.load_from_df(df[['user_id', 'product_id', 'rating']], reader)
trainset, testset = train_test_split(data, test_size=0.25)
# ๋ชจ๋ธ ํ์ต
model = SVD()
model.fit(trainset)
# ์์ธก ๋ฐ ํ๊ฐ
predictions = model.test(testset)
accuracy.rmse(predictions)
# 2. ๋ชจ๋ธ ์ ์ฅ ๋ฐ load
import joblib
# ๋ชจ๋ธ ์ ์ฅ
joblib.dump(model, 'svd_model.pkl')
# ๋ชจ๋ธ ๋ก๋
loaded_model = joblib.load('svd_model.pkl')
์คํ๋ง๋ถํธ ์ ํ๋ฆฌ์ผ์ด์ ๊ณผ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ํตํฉ
@Service
public class RecommendationService {
private final PythonInterpreter pythonInterpreter;
@Autowired
public RecommendationService() {
// PythonInterpreter๋ฅผ ์ฌ์ฉํ์ฌ Python ์คํฌ๋ฆฝํธ๋ฅผ ํธ์ถ
pythonInterpreter = new PythonInterpreter();
pythonInterpreter.exec("import joblib");
pythonInterpreter.exec("model = joblib.load('path/to/svd_model.pkl')");
}
public List<Product> getRecommendations(Long userId) {
// Python ์คํฌ๋ฆฝํธ ํธ์ถ ๋ฐ ์ถ์ฒ ์์ฑ
pythonInterpreter.set("user_id", userId);
pythonInterpreter.exec("recommendations = model.predict(user_id)");
// ์ถ์ฒ ๋ฆฌ์คํธ ๋ณํ ๋ฐ ๋ฐํ
// ...
return recommendations;
}
}
@RestController
@RequestMapping("/api/recommendations")
public class RecommendationController {
@Autowired
private RecommendationService recommendationService;
@GetMapping("/{userId}")
public ResponseEntity<List<Product>> getRecommendations(@PathVariable Long userId) {
List<Product> recommendations = recommendationService.getRecommendations(userId);
return ResponseEntity.ok(recommendations);
}
}
์ถ์ฒ : ์ถ์ฒ ์์คํ ๊ธฐ๋ณธ - ํ์ ํํฐ๋ง(Collaborative Filtering) - โ
์ ์ฌ๋ ์ธก์ ๋ฐฉ๋ฒ
๋ ๋ฐฉ๋ฒ ๋ชจ๋ ์ ์ฌ๋(๊ฑฐ๋ฆฌ)๋ฅผ ์ธก์ ํด์ ์ฌ์ฉ
์ผ๋ฐ์ ์ธ ๊ฑฐ๋ฆฌ ์ธก์ ๋ฐฉ๋ฒ๋ก 3๊ฐ์ง
Cosine Similarity
Pearson Correlation Similarity
Memory-based Approach์ ์ฅ๋จ์
์ฅ์
๋จ์
์ถ์ฒ : ์ถ์ฒ ์์คํ ๊ธฐ๋ณธ - ํ์ ํํฐ๋ง(Collaborative Filtering) - โก
์ฒซ ๋ฒ์งธ, MF(ํ๋ ฌ ๋ถํด)๋?
ex) User ๋ฐ Item ๋ชจ๋์ ๋ํด 5์ฐจ์ ์๋ฒ ๋ฉ( n_factor = 5 ) ๊ฐ ์๋ค๊ณ ๊ฐ์
MF๋ ์ฌ๋ฌ ๋ฐฉ๋ฒ ์ํ ๊ฐ๋ฅ
์ถ์ฒ : [๋ ผ๋ฌธ์์ฝ] ๋ฅ๋ฌ๋ ๊ด๋ จ ์ถ์ฒ ๋ชจ๋ธ - Survey(2019)
End-to-End ํ์ต
Inductive Biases(Generalization๊ณผ ์ ์ฌ)
ํฐ ๋ฐ์ดํฐ ๋ฐ ๋ณต์กํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐ ๊ฐ๋ฅ
Non-Linear Transformation
Representation Learning
Sequence Modeling
Flexibility
Keras, Tensorflow, Pytorch์ ๊ฐ์ Framework๋ฅผ ๊ฐ์ง๊ณ ์์.
Interpretability
Data Requirement
Extensive Hyper-parameter Tuning
๋จธ์ ๋ฌ๋์ ์ ๋ฐ์ ์ธ ํ๊ณ์ ์ผ๋ก, ๋งค์ฐ ๋ง์ ์์ Hyper-Parameter ๋ฌธ์ ๊ฐ ์์.
๋จ์ผ Hyper-Parameter๋ฅผ ์ฌ์ฉํ ์ ์๋ ์ฐ๊ตฌ๊ฐ ์งํ๋๊ณ ์๋ค๊ณ ํจ.
SOTA?
- ๊ฐ ๋ถ์ผ์ ๊ฐ์ฅ ์ข์ ์ฑ๋ฅ์ ๋ด๋ ๋ชจ๋ธ์ ๋ปํจ.
Autoencoder
ํ์ต ๋ฐฉ์
Autoencoder ๊ธฐ๋ฐ ํ์ ํํฐ๋ง
User๋ Item์ Partial Vector๋ฅผ ์
๋ ฅํ๋ฉด Output Layer์์ ์ฌ๊ตฌ์ฑ
- User์ ๋ฒกํฐ์์ ๋ ๋์ ๋ถ์ฐ์ ๊ฐ์ง๋ฏ๋ก, Item-AutoRec > User-AutoRec ์ฑ๋ฆฝ
Attention ๊ธฐ๋ฐ ์ถ์ฒ ์์คํ
Attention ๋ฉ์ปค๋์ฆ?
- ์ฌ๋์ด ์ ์ฒด ์ด๋ฏธ์ง๋ ๋ฌธ์ฅ ์ค ํน์ ํ ๋ถ๋ถ๋ง์ ์ง์คํ๋ ๊ฒ์์ ์์ด๋์ด๋ฅผ ์ป์
Attention Score๋ก Input์ ์ ์ํ
Attention ์ข ๋ฅ 2๊ฐ์ง : Vanilla Attention, Co-Attention
์ด์ธ์ ์์ธํ ๋ด์ฉ ๋ฐ ํฅํ ์ฐ๊ตฌ ๋ฐ ๋ฏธํด๊ฒฐ ๊ณผ์ ์ ๋ํ ๋ถ๋ถ์ ์ด ๊ณณ์ ์ฐธ๊ณ ํด์ฃผ์ธ์!
๐ [๋ ผ๋ฌธ์์ฝ] ๋ฅ๋ฌ๋ ๊ด๋ จ ์ถ์ฒ ๋ชจ๋ธ - Survey(2019)