Giter Club home page Giter Club logo

tagger's Introduction

tagger Follow

Project Status: Active - The project has reached a stable, usable state and is being actively developed.Build Status Coverage Status Version

tagger wraps the NLP and openNLP packages for easier part of speech tagging. tagger uses the openNLP annotator to compute "Penn Treebank parse annotations using the Apache OpenNLP chunking parser for English."

The main functions and descriptions are listed in the table below.

Function Description
tag_pos Tag parts of speech
select_tags Select specific part of speech tags from tag_pos
count_tags Cross tabs of tags by grouping variable

Table of Contents

Installation

To download the development version of tagger:

Download the zip ball or tar ball, decompress and run R CMD INSTALL on it, or use the pacman package to install the development version:

if (!require("pacman")) install.packages("pacman")
pacman::p_load_gh(c(
    "trinker/termco", 
    "trinker/coreNLPsetup",        
    "trinker/tagger"
))

Contact

You are welcome to:

Examples

The following examples demonstrate some of the functionality of tagger.

Load the Tools/Data

library(dplyr); library(tagger)

## 
## Attaching package: 'dplyr'

## The following objects are masked from 'package:stats':
## 
##     filter, lag

## The following object is masked from 'package:qdap':
## 
##     %>%

## The following object is masked from 'package:qdapTools':
## 
##     id

## The following objects are masked from 'package:qdapRegex':
## 
##     escape, explain

## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

data(presidential_debates_2012)
mwe <- data_frame(
    person = c("Tyler", "Norah", "Tyler"),
    talk = c(
        "I need $54 to go to the movies.",
        "They refuse to permit us to obtain the refuse permit",
        "This is the tagger package; like it?"
    )
)

Tagging

Let's begin with a minimal example.

tag_pos(mwe$talk)

## [1] "I/PRP need/VBP $/$ 54/CD to/TO go/VB to/TO the/DT movies/NNS ./."                     
## [2] "They/PRP refuse/VBP to/TO permit/VB us/PRP to/TO obtain/VB the/DT refuse/NN permit/NN"
## [3] "This/DT is/VBZ the/DT tagger/NN package/NN ;/: like/IN it/PRP ?/."

Note that the out put pretty pints but the underlying structure is simply a lst of named vectors, where the elements in the vectors are the tokens and the names are the part of speech tags. We can use c on the object to see it's true structure.

tag_pos(mwe$talk) %>%
    c()

## [[1]]
##      PRP      VBP        $       CD       TO       VB       TO       DT 
##      "I"   "need"      "$"     "54"     "to"     "go"     "to"    "the" 
##      NNS        . 
## "movies"      "." 
## 
## [[2]]
##      PRP      VBP       TO       VB      PRP       TO       VB       DT 
##   "They" "refuse"     "to" "permit"     "us"     "to" "obtain"    "the" 
##       NN       NN 
## "refuse" "permit" 
## 
## [[3]]
##        DT       VBZ        DT        NN        NN         :        IN 
##    "This"      "is"     "the"  "tagger" "package"       ";"    "like" 
##       PRP         . 
##      "it"       "?"

Let's try it on a larger example, the built in presidential_debates_2012 data set. It'll take 30 seconds or so to run, depending on the machine.

tag_pos(presidential_debates_2012$dialogue)

## 1.    We/PRP 'll/MD talk/VB about/IN specifically/RB ...
## 2.    But/CC what/WP do/VBP you/PRP support/VB the/DT ...
## 3.    What/WP I/PRP support/VBP is/VBZ no/DT change/NN ...
## 4.    And/CC the/DT president/NN supports/VBZ taking/VBG ...
## 5.    And/CC what/WP about/IN the/DT vouchers/NNS ?/.
## .
## .
## .
## 2908. Thank/VB you/PRP so/RB much/RB ./.
## 2909. Gentlemen/NNS ,/, thank/VB you/PRP both/DT so/RB ...
## 2910. That/DT brings/VBZ an/DT end/NN to/TO this/DT ...
## 2911. As/IN I/PRP always/RB do/VBP at/IN the/DT end/NN ...
## 2912. Good/JJ night/NN ./.

This output is built into tagger as the presidential_debates_2012_pos data set, which we'll use form this point on in the demo.

Note that the user may choose to use CoreNLP as a backend by setting engine = "coreNLP". To ensure that coreNLP is setup properly use check_setup.

Plotting

The user can generate a horizontal barplot of the used tags.

presidential_debates_2012_pos %>%
    plot()

Interpreting Tags

The tags generated by openNLP are from Penn Treebank. As such there are many tags, more than the few parts of speech we learned in grade school. Remembering the meaning of each tags may be difficult, therefore the penn_tags creates a left aligned data frame of the possible tags and their meaning.

penn_tags()

##    Tag  Description                                 
## 1  $    dollar                                      
## 2  ``   opening quotation mark                      
## 3  ''   closing quotation mark                      
## 4  (    opening parenthesis                         
## 5  )    closing parenthesis                         
## 6  ,    comma                                       
## 7  -    dash                                        
## 8  .    sentence terminator                         
## 9  :    colon or ellipsis                           
## 10 CC   conjunction, coordinating                   
## 11 CD   numeral, cardinal                           
## 12 DT   determiner                                  
## 13 EX   existential there                           
## 14 FW   foreign word                                
## 15 IN   preposition or conjunction, subordinating   
## 16 JJ   adjective or numeral, ordinal               
## 17 JJR  adjective, comparative                      
## 18 JJS  adjective, superlative                      
## 19 LS   list item marker                            
## 20 MD   modal auxiliary                             
## 21 NN   noun, common, singular or mass              
## 22 NNP  noun, proper, singular                      
## 23 NNPS noun, proper, plural                        
## 24 NNS  noun, common, plural                        
## 25 PDT  pre-determiner                              
## 26 POS  genitive marker                             
## 27 PRP  pronoun, personal                           
## 28 PRP$ pronoun, possessive                         
## 29 RB   adverb                                      
## 30 RBR  adverb, comparative                         
## 31 RBS  adverb, superlative                         
## 32 RP   particle                                    
## 33 SYM  symbol                                      
## 34 TO   "to" as preposition or infinitive marker    
## 35 UH   interjection                                
## 36 VB   verb, base form                             
## 37 VBD  verb, past tense                            
## 38 VBG  verb, present participle or gerund          
## 39 VBN  verb, past participle                       
## 40 VBP  verb, present tense, not 3rd person singular
## 41 VBZ  verb, present tense, 3rd person singular    
## 42 WDT  WH-determiner                               
## 43 WP   WH-pronoun                                  
## 44 WP$  WH-pronoun, possessive                      
## 45 WRB  Wh-adverb

Counts

The user can generate a count of the tags by grouping variable as well. The number of columns explodes quickly, even with this minimal example.

tag_pos(mwe$talk) %>%
    count_tags(mwe$person) 

##   person n.tokens       $        .       :      CD       DT      IN
## 1  Norah       10       0        0       0       0 1(10.0%)       0
## 2  Tyler       19 1(5.3%) 2(10.5%) 1(5.3%) 1(5.3%) 3(15.8%) 1(5.3%)
##         NN     NNS      PRP       TO       VB      VBP     VBZ
## 1 2(20.0%)       0 2(20.0%) 2(20.0%) 2(20.0%) 1(10.0%)       0
## 2 2(10.5%) 1(5.3%) 2(10.5%) 2(10.5%)  1(5.3%)  1(5.3%) 1(5.3%)

The default is a pretty printing (counts + proportions) that can be turned off to print raw counts only.

tag_pos(mwe$talk) %>%
    count_tags(mwe$person) %>%
    print(pretty = FALSE)

##    person n.tokens $ . : CD DT IN NN NNS PRP TO VB VBP VBZ
## 1:  Tyler       19 1 2 1  1  3  1  2   1   2  2  1   1   1
## 2:  Norah       10 0 0 0  0  1  0  2   0   2  2  2   1   0

Select Tags

The user may wish to select specific tags. The select_tags function enables selection of specific tags via element matching (which can be negated) or regular expression.

Here we select only the nouns.

presidential_debates_2012_pos %>%
    select_tags(c("NN", "NNP", "NNPS", "NNS"))

## 1.    health/NN care/NN moment/NN
## 2.    voucher/NN system/NN Governor/NNP
## 3.    change/NN retirees/NNS retirees/NNS Medicare/NNP
## 4.    president/NN dollar/NN program/NN
## 5.    vouchers/NNS
## .
## .
## .
## 2908. 
## 2909. Gentlemen/NNS
## 2910. end/NN year/NN debates/NNS Lynn/NNP University/NNP ...
## 2911. end/NN debates/NNS words/NNS mom/NN vote/NN
## 2912. night/NN

This could also have been accomplished with a simpler regex call by setting regex = TRUE.

presidential_debates_2012_pos %>%
    select_tags("NN", regex=TRUE)

## 1.    health/NN care/NN moment/NN
## 2.    voucher/NN system/NN Governor/NNP
## 3.    change/NN retirees/NNS retirees/NNS Medicare/NNP
## 4.    president/NN dollar/NN program/NN
## 5.    vouchers/NNS
## .
## .
## .
## 2908. 
## 2909. Gentlemen/NNS
## 2910. end/NN year/NN debates/NNS Lynn/NNP University/NNP ...
## 2911. end/NN debates/NNS words/NNS mom/NN vote/NN
## 2912. night/NN

In this way we could quickly select the nouns and verbs with the following call.

presidential_debates_2012_pos %>%
    select_tags("^(VB|NN)", regex=TRUE)

## 1.    talk/VB health/NN care/NN moment/NN
## 2.    do/VBP support/VB voucher/NN system/NN Governor/NNP
## 3.    support/VBP is/VBZ change/NN retirees/NNS ...
## 4.    president/NN supports/VBZ taking/VBG dollar/NN ...
## 5.    vouchers/NNS
## .
## .
## .
## 2908. Thank/VB
## 2909. Gentlemen/NNS thank/VB
## 2910. brings/VBZ end/NN year/NN debates/NNS want/VBP ...
## 2911. do/VBP end/NN debates/NNS leave/VBP words/NNS ...
## 2912. night/NN

Note that the output is a tag_pos class and the plotting, count_tags, and as_word_tag functions can be used on the result.

presidential_debates_2012_pos %>%
    select_tags("^(VB|NN)", regex=TRUE) %>%
    plot()

presidential_debates_2012_pos %>%
    select_tags("^(VB|NN)", regex=TRUE) %>%
    count_tags()

## # A tibble: 2,912 × 11
##    n.tokens        NN      NNP  NNPS       NNS       VB   VBD      VBG
##       <dbl>     <chr>    <chr> <chr>     <chr>    <chr> <chr>    <chr>
## 1         4  3(75.0%)        0     0         0 1(25.0%)     0        0
## 2         5  2(40.0%) 1(20.0%)     0         0 1(20.0%)     0        0
## 3         6  1(16.7%) 1(16.7%)     0  2(33.3%)        0     0        0
## 4         5  3(60.0%)        0     0         0        0     0 1(20.0%)
## 5         1         0        0     0 1(100.0%)        0     0        0
## 6         3  1(33.3%)        0     0         0        0     0        0
## 7        16  4(25.0%) 2(12.5%)     0   1(6.2%) 4(25.0%)     0  1(6.2%)
## 8         1 1(100.0%)        0     0         0        0     0        0
## 9         6  1(16.7%)        0     0  1(16.7%) 3(50.0%)     0        0
## 10        5  2(40.0%)        0     0         0 2(40.0%)     0        0
## # ... with 2,902 more rows, and 3 more variables: VBN <chr>, VBP <chr>,
## #   VBZ <chr>

Altering Tag Display

As Word Tags

The traditional way to display tags is to incorporate them into the sentence, placing them after/before their respective token, separated by a forward slash (e.g., talk/VB). This is the default printing style of tag_pos though not truly the structure of the output. The user can coerce the underlying structure with the as_word_tag function, converting the named list of vectors into a list of part of speech incorporated, unnamed vectors. Below I only print the first 6 elements of as_word_tag.

presidential_debates_2012_pos %>%
    as_word_tag() %>%
    head()

## [1] "We/PRP 'll/MD talk/VB about/IN specifically/RB about/IN health/NN care/NN in/IN a/DT moment/NN ./."                                        
## [2] "But/CC what/WP do/VBP you/PRP support/VB the/DT voucher/NN system/NN ,/, Governor/NNP ?/."                                                 
## [3] "What/WP I/PRP support/VBP is/VBZ no/DT change/NN for/IN current/JJ retirees/NNS and/CC near/IN retirees/NNS to/TO Medicare/NNP ./."        
## [4] "And/CC the/DT president/NN supports/VBZ taking/VBG dollar/NN seven/CD hundred/CD sixteen/CD billion/CD out/IN of/IN that/DT program/NN ./."
## [5] "And/CC what/WP about/IN the/DT vouchers/NNS ?/."                                                                                           
## [6] "So/IN that/DT 's/VBZ that/DT 's/VBZ number/NN one/CD ./."

As Tuples

Python uses a tuple construction of parts of speech to display tags. This can be a useful structure. Essentially the structure is a lists of lists of two element vectors. Each vector contains a word and a part of speech tag. as_tuple uses the following R structuring:

list(list(c("word", "tag"), c("word", "tag")), list(c("word", "tag")))

but prints to the console in the Python way. Using print(as_tuple(x), truncate=Inf, file="out.txt") allows the user to print to an external file.

tag_pos(mwe$talk) %>%
    as_tuple() %>%
    print(truncate=Inf)

## [[("I", "PRP"), ("need", "VBP"), ("$", "$"), ("54", "CD"), ("to", "TO"), ("go", "VB"), ("to", "TO"), ("the", "DT"), ("movies", "NNS"), (".", ".")], [("They", "PRP"), ("refuse", "VBP"), ("to", "TO"), ("permit", "VB"), ("us", "PRP"), ("to", "TO"), ("obtain", "VB"), ("the", "DT"), ("refuse", "NN"), ("permit", "NN")], [("This", "DT"), ("is", "VBZ"), ("the", "DT"), ("tagger", "NN"), ("package", "NN"), (";", ":"), ("like", "IN"), ("it", "PRP"), ("?", ".")]]

As Universal Tags

Petrov, Das, & McDonald (2011) provide a mapping to convert Penn Treebank tags into universal part of speech tags. The as_universal function harnesses this mapping.

tag_pos(mwe$talk) %>%
    as_universal()

## [1] "I/PRON need/VERB $/. 54/NUM to/PRT go/VERB to/PRT the/DET movies/NOUN ./."                          
## [2] "They/PRON refuse/VERB to/PRT permit/VERB us/PRON to/PRT obtain/VERB the/DET refuse/NOUN permit/NOUN"
## [3] "This/DET is/VERB the/DET tagger/NOUN package/NOUN ;/. like/ADP it/PRON ?/."

The out put is a tag_pos object and thus has a generic plot method.

tag_pos(mwe$talk) %>%
    as_universal() %>%
    plot()

tag_pos(mwe$talk) %>%
    as_universal() %>%
    count_tags()

##   n.tokens        .      ADP      DET     NOUN      NUM     PRON      PRT
## 1       10 2(20.0%)        0 1(10.0%) 1(10.0%) 1(10.0%) 1(10.0%) 2(20.0%)
## 2       10        0        0 1(10.0%) 2(20.0%)        0 2(20.0%) 2(20.0%)
## 3        9 2(22.2%) 1(11.1%) 2(22.2%) 2(22.2%)        0 1(11.1%)        0
##       VERB
## 1 2(20.0%)
## 2 3(30.0%)
## 3 1(11.1%)

As Basic Tags

as_basic provides an even more coarse tagset than as_universal. Basic tags include: (a) nouns, (b) adjectives, (c) prepositions, (d) articles, (e) verb, (f) pronouns, (g) adverbs, (h) interjections, & (i) conjunctions. The X and . tags are retained for punctuation and unclassified parts of speech.

tag_pos(mwe$talk) %>%
    as_basic()

## [1] "I/pronoun need/verb $/. 54/adjective to/preposition go/verb to/preposition the/article movies/noun ./."                       
## [2] "They/pronoun refuse/verb to/preposition permit/verb us/pronoun to/preposition obtain/verb the/article refuse/noun permit/noun"
## [3] "This/adjective is/verb the/article tagger/noun package/noun ;/. like/preposition it/pronoun ?/."

This tagset can be useful for more coarse purposes, including formality (Heylighen & Dewaele, 2002) scoring.

  • Heylighen, F., & Dewaele, J.M. (2002). Variation in the contextuality of language: An empirical measure. Context in Context, Special issue of Foundations of Science, 7 (3), 293-340.

The output is a tag_pos object and thus has a generic plot method.

tag_pos(mwe$talk) %>%
    as_basic() %>%
    plot()

tag_pos(mwe$talk) %>%
    as_basic() %>%
    count_tags()

##   n.tokens        . adjective  article     noun preposition  pronoun
## 1       10 2(20.0%)  1(10.0%) 1(10.0%) 1(10.0%)    2(20.0%) 1(10.0%)
## 2       10        0         0 1(10.0%) 2(20.0%)    2(20.0%) 2(20.0%)
## 3        9 2(22.2%)  1(11.1%) 1(11.1%) 2(22.2%)    1(11.1%) 1(11.1%)
##       verb
## 1 2(20.0%)
## 2 3(30.0%)
## 3 1(11.1%)

tagger's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tagger's Issues

Include option for other languages

Thanks for developing this package – it's really helpful. One question: openNLP offers POS taggers for several other languages (http://opennlp.sourceforge.net/models-1.5/).

They can be loaded easily by installing the respective package, for instance for the Dutch model:

install.packages("openNLPmodels.nl", repos = "http://datacube.wu.ac.at/", type = "source")

If I want to use these languages for my POS tagging, in openNLP I simply specify the language for the annotators (see e.g. ?Maxent_POS_Tag_Annotator).

Thus, could we implement this option for tidypos as well? I assume we need to change lines 82 and 83 in the tag_pos.R file to:

PTA <- openNLP::Maxent_POS_Tag_Annotator(language = "en")
WTA <- openNLP::Maxent_Word_Token_Annotator(language = "en")

and add a language option to the tag_pos.R function. We should set English as the default, but makes it possible to change the language.

I hope that these changes would do the job, but I am not absolutely sure whether the language option needs to be included in other parts of the function. If you let me know whether more changes are needed or not (if yes, which ones?), I am happy to make a pull request.

integrate coreNLP

tag_pos <- function(text.var, lib = "coreNLP", parse.annotator = easy_parse_annotator(), 
    java.path = "java",
    element.chunks = floor(2000 * (23.5/mean(sapply(text.var, nchar), na.rm = TRUE))), ...){

    len <- length(text.var)

    ## locate empty or missing text elements
    nas <- sort(union(which(is.na(text.var)), grep("^\\s*$", text.var)))

    ## replace empty text with a period
    if(!identical(nas, integer(0))){
       text.var[nas] <- "."
    }

    ## Chunking the text into memory sized chunks:
    ## caluclate the start/end indexes of the chunks
    ends <- c(utils::tail(seq(0, by = element.chunks,
        length.out = ceiling(len/element.chunks)), -1), len)
    starts <- c(1, utils::head(ends + 1 , -1))

    ## chunk the text
    text_list <- Map(function(s, e) {text.var[s:e]}, starts, ends)

    if (lib == "coreNLP") {
        ## loop through the chunks and tag them
        out <- unlist(lapply(text_list, function(x){
            x <- core_tagger(x, java = java.path, ...)
            gc()
            x
        }), recursive = FALSE)
    } else {
        ## Need pos and word token annotations.
        PTA <- openNLP::Maxent_POS_Tag_Annotator()
        WTA <- openNLP::Maxent_Word_Token_Annotator()
    
        ## loop through the chunks and tag them
        out <- unlist(lapply(text_list, function(x){
            x <- tagPOS(x, PTA, WTA)
            gc()
            x
        }), recursive = FALSE)

    }

    if(!identical(nas, integer(0))){
       out[nas] <- NA
    }

    class(out) <- c("tag_pos", class(out))
    out
}




core_tagger <- function (text.var,
    stanford.tagger = stansent::coreNLP_loc(), java.path = "java", ...) {

    if (!file.exists(stanford.tagger)) {
        check_stanford_installed(...)
    }

    text.var <- gsub("[.?!](?!$)", " ", gsub("(?<=[.?!])[.?!]+$", "", text.var, perl = TRUE), perl = TRUE)

    #message("\nAnalyzing text for sentiment...\n")

    cmd <- sprintf(
        "%s -cp \"%s/*\" -mx5g edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators \"tokenize,ssplit,pos\" -ssplit.eolonly",
        #"%s -cp \"%s/*\" -mx5g edu.stanford.nlp.sentiment.SentimentPipeline -stdin",
        java.path, stanford.tagger
    )
    results <- system(cmd, input = text.var, intern = TRUE, ignore.stderr = TRUE)

    starts <- grep("^Sentence #", results)
    ends <- c(utils::tail(starts, -1) - 1, length(results))

    Map(function(s, e){
        results2 <- grep("^\\[Text", results[s:e], value=TRUE)
        wrds <- gsub("(^[^=]+=)([^ ]+)(\\s.+$)", "\\2", results2)
        names(wrds) <- gsub("(^.+?PartOfSpeech=)([^]]+)(\\]$)", "\\2", results2)
        wrds
    }, starts, ends)

}

tag_pos(c("i like it.", "the dog ate the cat.")) 

tagPOS <- tagger:::tagPOS
tag_pos(c("i like it.", "the dog ate the cat."), 'openNLP')


Problem writing output to a csv

Hi,

Thank you for the tagger package. It is terrific. I encounter a problem writing it to a csv file.

I get this error every time I try writing it to an output file (txt and csv)

Error message:

Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, :
arguments imply differing number of rows: 2, 3, 4, 5, 1, 6, 0, 7, 8, 9
In addition: Warning message:
In write.csv(x, file = "D:\path...\postagging.csv", :
attempt to set 'append' ignored

I am also not able to coerce the output into a matrix or a data frame.

Please help!

tag_pos splitting tokens inapproptiately

@trinker just started using tagger and really like it so far - thanks for your effort.

I noticed in trying to add parts of speech to an existing data.frame of words that the number of pos elements being output was greater that the number of words being input. So far I've traced it down to two things.

  1. Acronyms with three or more letters - separated by periods. For example, U.S.C. (United States Code) gets split into U.S. and C.
  2. Words with apostrophes get split at the apostrophe.

Looking at the package documentation, I haven't found a way to change this behavior. Is this a bug or am I missing something?

unable to install package

Hi,

I Had to reinstall OS on my system, so I have to now install all the R libraries. I tried the zip, tar, and the pacman command versions to install these packages. I also tried "install_github(trinker/tagger)"-devtools library. I could only install coreNLPsetup, and not the other two. I tried this approach on other machines, and got same results. Please help! Thank you!

Final error message I receive is here (64 bit machine, OS- Windows 7, RAM 8GB, also tried on an Optiplex 64 bit, 32GB RAM). I tried installing only tagger when I got this error. Error message will include termco if I included it too. No change :(

ERROR: dependency 'termco' is not available for package 'tagger'
* removing 'C:/Users/KD/Documents/R/win-library/3.4/tagger'
Warning message:
In pacman::p_load_gh(c("trinker/tagger")) : 
Failed to install/load:
trinker/tagger

Termco and tagger

Warning message:
In pacman::p_load_gh(c("trinker/termco", "trinker/tagger")) : 
Failed to install/load:
trinker/termco, trinker/tagger

Error on single word:

tagger::tag_pos('runs')
Error in substr(x, i, j) : argument "j" is missing, with no default

typo readme

`The tags used by openNLP are utilize Penn Treebank.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.