Интерактивная визуализация постов с фан-страниц Facebook
Цель
Цель этого короткого сообщения в блоге - продемонстрировать интерактивный инструмент визуализации с результатами обработки естественного языка с помощью алгоритма word2vec на сообщениях FB из аналогичных медиа-каналов.
Результат
Созданный интерактивный инструмент находится здесь.
Из анимированного GIF ниже видно, что сообщения с похожим содержанием ближе друг к другу благодаря алгоритму word2vec! Мы также заметили, что сообщения из National Geographic (точки данных выделены розовым цветом) более сгруппированы в середине, чем сообщения из других каналов, что позволяет предположить, что они либо сосредоточены на более узких темах, либо используют аналогичные формулировки в Facebook.
Подход
Этот пост в блоге вдохновлен постом Макса Вульфа, в котором он использовал Spark и Python для визуализации заголовков кликбейтов из популярных новостных каналов. Мы изменили его подход, так что аналогичная аналогия может быть проделана в R с другими инструментами. Настоятельно рекомендуется просмотреть алгоритм word2vec здесь и сообщение приложения здесь, прежде чем продолжить.
Используемые инструменты: fanpager, R, plotly
- Удалите последние сообщения со всех 4 фан-страниц медиа-каналов.
Нажмите здесь, чтобы просмотреть пошаговое руководство. - Обработка контента с помощью алгоритма НЛП word2vec
Нажмите здесь, чтобы увидеть введение в алгоритм.
Нажмите здесь, чтобы просмотреть пошаговое руководство - Визуализируйте результаты с помощью Plotly (см. Полный код R в конце)
Выделять
Изначально мы хотели видеть только векторизованный результат без стоп-слов в сообщениях National Geographic и Discovery Channel.
Мы выполнили t-NSE для преобразования 100-размерных векторов word2vec в 2-мерные для 2D-визуализации на диаграмме рассеяния. Замечено, что если мы удалим стоп-слова, такие как the, a, и that, сообщения National Geographic будут ближе друг к другу, образуя более плотную S-образную форму, а сообщения от Discovery сформировали более широкую S-образную форму с кластером справа, что указывает на большее сходство между этими сообщениями.
В то время как t-SNE имеет тенденцию включать как можно больше информации о многомерных наборах данных, PCA стремится сохранить структуру данных с линейной аппроксимацией.
Сначала мы рассмотрим производительность от PCA. Он показывает, что, используя только 2 главных компонента, мы можем представить более 95% исходных векторов!
Результат PCA со стоп-словами кажется более интересным. Он показал, что сообщения от National Geographic больше ориентированы на левую сторону, в то время как сообщения от Discovery имеют тенденцию смещаться вправо, в сторону от центра.
Кажется, что PCA со стоп-словами может наградить нас более интересными результатами. Давайте продолжим и включим посты из Animal Planet и History Channel.
Хотя производительность PCA упала, мы все еще могли отображать более 90% исходных векторов.
Созданный интерактивный инструмент находится здесь.
Теперь мы можем четко наблюдать следующее:
1… Большинство сообщений National Geographic похожи.
2… Discovery Channel предлагает как узкие, так и более широкие сообщения с меньшим количеством контента
3… Сообщения History Channel более сосредоточены в нижней части
4 … Animal Planet охватывает более широкий круг тем, относительно
Код R
#Data Cleaning animal <- read.csv("animal.csv",header=FALSE) animal$V1 <- paste(animal$V1,animal$V2,animal$V3,animal$V4,animal$V5,animal$V6,animal$V7,sep="") animal$V1 <- sub(".*;","",animal$V1) animal$V1 <- sub('""""','',animal$V1) animal$V1 <- sub('"""','',animal$V1) animal$V1 <- sub('""','',animal$V1) animal$V1 <- sub('"','',animal$V1) animal$V1 <- sub('"','',animal$V1) animal$V1 <- sub('"','',animal$V1) #Prepare the dataset train = text$title train = gsub("[[:punct:]]", "", train) train <- tolower(train) stopWords <- stopwords("en") '%nin%' <- Negate('%in%') train <- lapply(train, function(x) { t <- unlist(strsplit(x, " ")) t[t %nin% stopWords] }) train.df = as.data.frame(do.call(rbind, train)) write.table(train.df,"text_data.txt") write(train,"text_data.txt") #Input words to model model=word2vec(train_file = "text_data.txt",output_file = "vec.bin",binary=1) #Convert binary to text format bin_to_txt("vec.bin","model1text.txt") #Convert .txt to .cvs model1 <- read.table("model1text.txt",fill=TRUE) write.csv(model1,"model1.csv") m1 <- read.csv("model1.csv") #Apply word vectors to posts s <- strsplit(text$title, split = " ") new <- data.frame(V1 = rep(text$id, sapply(s, length)), V2 = unlist(s)) colnames(new) <- c("id","word") colnames(m1)[1] <- "word" new <- merge(new,m1,by="word") new2 <- aggregate(V2 ~ id, new, mean) for (i in 4:102){ new3 <- aggregate(new[,i] ~ id, new, mean) new2 <- merge (new2,new3,by="id") } colnames(new2)[1] <- "id" colnames(new2)[2:101] <- paste("V", 1:100, sep="") new2$id <- as.factor(new2$id) #t-SNE on posts set.seed(1) tsne <- Rtsne(new2, dims = 2, perplexity=100, verbose=TRUE, max_iter = 500) t = as.data.frame(tsne$Y) id <- subset(new2,select="id") t <- merge(id,t,by=0) fanpage <- text[,c(1:2)] final <- merge(fanpage,t,by="id") plot.t <- ggplot(final,aes(V1, V2, color = final$fanpage))+geom_point(alpha=0.7,size=1) plot.t #PCA on posts pcadata <- new2 pcadata$id <- NULL pr.out=prcomp(pcadata, scale=TRUE) pr.out$sdev pr.var=pr.out$sdev ^2 pve=pr.var/sum(pr.var) pve plot(pve, xlab="Principal Component", ylab="Proportion of Variance Explained ", ylim=c(0,1),type="b") plot(cumsum(pve), xlab="Principal Component ", ylab=" Cumulative Proportion of Variance Explained ", ylim=c(0,1), type="b") pcadata2 <- scale(pcadata, pr.out$center, pr.out$scale) %*% pr.out$rotation p1 <- merge(id,pcadata2,by=0) pfinal <- merge(fanpage,p1,by="id") pfinal <- merge(pfinal,text,by="id") #plotly p <- plot_ly(pfinal, x = ~PC1, y = ~PC2, color = ~fanpage.x, type = 'scatter', mode = 'markers',hoverinfo = 'text',text = ~title) plotly_POST(p, filename="word2vec")
Это резюмирует сообщение в блоге, надеюсь, оно будет полезным и интересным.
В будущих приложениях мы можем применить алгоритм word2vec к неструктурированным данным, таким как отзывы клиентов, для улучшения прогнозных моделей.
Вопросы, комментарии или проблемы?
[email protected]