Text Mining Action Set
Derive Topics from a Document Collection
This section contains PROC CAS code.
Note: Input data must be accessible in your CAS session, either as a CAS table or as a transient-scope table. A CAS table has a two-level name: the first level is your CAS engine libref, and the second level is the table name. You refer to this table in the CAS procedure by specifying only the second level. For more information about two-level names, see Chapter 2, Shared Concepts (SAS Viya: Machine Learning Procedures). A transient-scope table is called directly from the action and exists in memory for the duration of the action. For more information about accessing data, see SAS Viya: System Programming Guide. For more information about PROC CAS and programming in CASL, see SAS Cloud Analytic Services: CASL Programmer’s Guide and SAS Cloud Analytic Services: CASL Reference.
This example demonstrates how to derive topics from a collection by using the tmMine action. The following DATA step creates an input data table named mycas.reviews. This step assumes that the CAS engine libref is named mycas, but you can substitute any appropriately named CAS engine libref.
data mycas.reviews;
infile datalines delimiter='|' missover;
length text $300 category $20;
input text$ positive category$ did;
datalines;
This is the greatest phone ever! love it! It can replace my tv! |1|electronics|1
The phone's battery life is too short and screen resolution is low.|0|electronics|2
The screen resolution is low, but I love this tv. Good viewing.|1|electronics|3
The movie itself is great and I liked watching it. Good acting! |1|movies|4
The movie's story is boring and the acting is poor.|0|movies|5
I watched this movie but it was boring. |0|movies|6
The book has a terrific plot!|1|books |7
The book's plot was suspenseful. Good read.|1|books|8
I love the author, but this book is a waste of time to read.|0|books|9
;
run;
The following PROC CAS step loads the included stop list into the active caslib for use:
proc cas;
loadtable caslib="ReferenceData" path="en_stoplist.sashdat";
run;
quit;
The following PROC CAS step calls the tmMine action, which parses the text, applies the stop list, calculates the SVD factorization, and discovers topics all in a single action. When the action completes, Output 39.1.1 through Output 39.1.3 are printed.
proc cas;
loadactionset "textMining";
action tmMine;
param
docId="did"
documents={ name="reviews"}
text="text"
nounGroups= False
tagging = True
stemming= True
stopList ={ name="en_stoplist"}
parseConfig={name="config", replace=TRUE}
parent ={ name="parent",replace=TRUE}
offset ={name="offset",replace=TRUE}
terms ={ name="terms", replace=TRUE}
reduce=2
k=3
docPro ={ name="docpro", replace=TRUE}
topics ={ name="topics", replace=TRUE}
u ={ name="svdu", replace=TRUE}
numLabels=3
topicDecision=True
;
action table.fetch /table="topics", orderBy="_TopicID_"; run;
action table.fetch /table="docpro", orderBy="did"; run;
action table.fetch /table="svdu", orderBy="_TermNum_"; run;
run;
quit;
Output 39.1.1 displays the contents of the mycas.topics table, which contains the discovered topics..
Output 39.1.1: Discovered Topics
| Selected Rows from Table TOPICS | |||||||
|---|---|---|---|---|---|---|---|
| _Index_ | Topic ID | Topic | Category | Number of Terms | Number of Docs | Term Cutoff | Document Cutoff |
| 1 | 1 | book, plot, read | Mult | 3 | 2 | 0.381 | 0.65 |
| 2 | 2 | movie, +bore, +watch | Mult | 4 | 3 | 0.385 | 0.632 |
| 3 | 3 | +television, phone, resolution | Mult | 4 | 3 | 0.385 | 0.524 |
Output 39.1.2 displays the contents of the mycas.docpro table, which contains the relationship of each document to each topic.
Output 39.1.2: Document Projections
| Selected Rows from Table DOCPRO | |||||||
|---|---|---|---|---|---|---|---|
| _Index_ | did | Score for "book, plot, read" | Score for "movie, +bore, +watch" | Score for "+television, phone, resolution" | book, plot, read | movie, +bore, +watch | television, phone, resolution |
| 1 | 1 | 0 | 0 | 0.5798821773 | 0 | 0 | 1 |
| 2 | 2 | 0 | 0 | 0.6905117599 | 0 | 0 | 1 |
| 3 | 3 | 0 | 0 | 0.6110259518 | 0 | 0 | 1 |
| 4 | 4 | 0 | 0.6825195 | 0 | 0 | 1 | 0 |
| 5 | 5 | 0 | 0.7457203512 | 0 | 0 | 1 | 0 |
| 6 | 6 | 0 | 0.8399661992 | 0 | 0 | 1 | 0 |
| 7 | 7 | 0.8185079558 | 0 | 0 | 1 | 0 | 0 |
| 8 | 8 | 0.8608494806 | 0 | 0 | 1 | 0 | 0 |
| 9 | 9 | 0.6458854573 | 0 | 0 | 0 | 0 | 0 |
Output 39.1.3 displays the contents of the mycas.svdu table, which contains the topic score of each term to each topic in the training data.
Output 39.1.3: Relationship between Topics and Terms
| Selected Rows from Table SVDU | ||||
|---|---|---|---|---|
| _Index_ | _TermNum_ | _Col1_ | _Col2_ | _Col3_ |
| 1 | 1 | -0.030316754 | 0.2151383406 | 0.2264079152 |
| 2 | 2 | -0.023548807 | 0.0108277192 | 0.4187120658 |
| 3 | 3 | 0.0005739315 | 0.5119842534 | -0.023157874 |
| 4 | 4 | 0.4942887978 | -0.017434609 | 0.0361238772 |
| 5 | 5 | 0.006516217 | 0.4386106117 | 0.0034250391 |
| 6 | 6 | 0.1556906713 | -0.036380438 | 0.378769758 |
| 7 | 7 | -0.023118229 | -0.024552378 | 0.4631866963 |
| 8 | 8 | -0.012714918 | -0.02769837 | 0.4603405044 |
| 9 | 9 | -0.019071159 | 0.4704832817 | -0.019501009 |
| 10 | 10 | 0.5951267514 | -0.021917194 | -0.019394378 |
| 11 | 11 | 0.0141264472 | 0.4927909226 | -0.047333542 |
| 12 | 12 | 0.5785006335 | -0.004751182 | -0.081927976 |
| 13 | 13 | -0.023548807 | 0.0108277192 | 0.4187120658 |
| 14 | 14 | 0.1981660672 | 0.1768502227 | 0.1289030697 |
Derive Topics from a Document Collection
This section contains Lua code.
s:upload{'reviews.csv', casout={name='reviews'}}
--s:loadtable(caslib="ReferenceData",path="en_stoplist.sashdat")
s:loadtable{caslib="casuser",path="en_stoplist.sashdat"}
-- Load action sets
s:loadactionset{actionset='textmining'}
-- Discover topics and Doc Projections
s:tmMine{
docid='did',
docpro={name='docpro',replace=True},
documents='reviews',
k=3,
nounGroups=false,
numLabels=3,
offset={name='offset',replace=true},
parent={name='parent',replace=true},
parseConfig={name='config',replace=true},
reduce=2,
stopList='en_stoplist',
tagging=true,
terms={name='terms',replace=true},
text='text',
topicDecision=true,
topics={name='topics',replace=True},
u={name='svdu',replace=True},
}
-- discovered topics
r = s:fetch{table={name="topics"}}
print(r.Fetch)
-- relationship of each document to each topic
r = s:fetch{table='docpro'}
print(r.Fetch)
-- relationship of each term to each topic
r = s:fetch{table='svdu'}
print(r.Fetch)
Derive Topics from a Document Collection
This section contains Python code.
# Create training data
from io import StringIO
reviews = StringIO('''text,positive,category,did
"This is the greatest phone ever! love it! It can replace my tv!",1,electronics,1
"The phone's battery life is too short and screen resolution is low.",0,electronics,2
"The screen resolution is low, but I love this tv. Good viewing.",1,electronics,3
"The movie itself is great and I liked watching it. Good acting!",1,movies,4
"The movie's story is boring and the acting is poor.",0,movies,5
"I watched this movie but it was boring..",0,movies,6
"The book has a terrific plot!",1,books,7
"The book's plot was suspenseful. Good read.",1,books,8
"I love the author, but this book is a waste of time to read.",0,books,9''')
handler = dmh.CSV(reviews, skipinitialspace=True)
s.addtable(table='reviews', **handler.args.addtable)
s.loadtable(caslib="ReferenceData",path="en_stoplist.sashdat")
# Create testing data
score_reviews = StringIO('''text,did
"Loved the movie! I watched it twice.",1
"I liked the book. Great read! Good Plot!",2''')
handler = dmh.CSV(score_reviews, skipinitialspace=True)
s.addtable(table='score_reviews', **handler.args.addtable)
s.builtins.loadActionSet(actionSet="textMining") # 1
s.textMining.tmMine(docId="did", # 2
docPro={"name":"docpro", "replace":True},
documents={"name":"reviews"},
k=3,
nounGroups=False,
numLabels=3,
offset={"name":"offset", "replace":True},
parent={"name":"parent", "replace":True},
parseConfig={"name":"config", "replace":True},
reduce=2,
stopList={"name":"en_stopList"},
tagging=True,
terms={"name":"terms", "replace":True},
text="text",
topicDecision=True,
topics={"name":"topics", "replace":True},
u={"name":"svdu", "replace":True}
)
#discovered topics
print(s.fetch(table='topics',orderBy='_TopicID_'))
#relationship of each document to each topic
print(s.fetch (table='docpro',orderBy='did'))
#relationship of each term to each topic
print(s.fetch(table='svdu', orderBy='_TermNum_'))
Derive Topics from a Document Collection
This example is not available for the R programming language.