Recommender Engine Action Set
Running the recBpr Action on User Community Website Data
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 shows how to use the recBpr action to train a Bayesian personalized ranking model from observations in a data table. The usersCommunity data set includes a subset of the click events over a period of time on a peer-to-peer support community website. Each web page (item) on the site belongs to a board that includes a number of topics of specific interest. The same user might have viewed the same web page multiple times. Also, in this data set, it is indicated whether or not the questions within the topic have been resolved. For each click event, the user ID and item ID are recorded. This data set includes 40,000 click events (observations).
The following code includes the DATA step that generates the data table mycas.usersCommunity. You can find the complete DATA step here:
https://support.sas.com/documentation/onlinedoc/viya/examples.htm
This statement assumes that your CAS engine libref is named mycas, but you can substitute any appropriately defined CAS engine libref.
data mycas.usersCommunity;
input itemid boardid userid isSolvedTopic;
datalines;
... more lines ...
The following statements train a Bayesian personalized ranking model on the usersCommunity data by using the recBpr action:
proc cas;
loadactionset "recommenderEngine";
action recBpr result=R / table={name="usersCommunity"},
outModel={name="factorsOut", replace=true},
inputs={"userid", "itemid"},
nominals={"userid", "itemid"},
userId="userid",
itemId="itemid",
maxIter=20, nFactors=10, learnStep=0.01, regularization=0.01,
savestate={name="savestatefile"}
;
run;
The following statements print the first 10 observations in the mycas.factorsOut data table, which includes some of the rows that are related to the latent factors for users. The output is shown in Output 33.1.1.
proc print data=mycas.factorsOut(obs=10);
run;
Output 33.1.1: Factors
| Obs | Variable | Level | Bias | Factor1 | Factor2 | Factor3 | Factor4 | Factor5 | Factor6 | Factor7 | Factor8 | Factor9 | Factor10 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | _GLOBAL_ | 0 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | 0.00000 | |
| 2 | userid | 1000 | 0 | -0.26163 | 0.88969 | -0.76059 | -0.03296 | -0.15550 | -0.68454 | -0.81456 | -0.02390 | 0.18829 | -0.07736 |
| 3 | userid | 1001 | 0 | 1.26229 | -0.54745 | 1.26211 | -0.10954 | -0.75401 | 0.67516 | -0.46804 | 0.76235 | 0.39493 | 1.10694 |
| 4 | userid | 1002 | 0 | 0.38487 | 0.34352 | -0.74136 | 0.20691 | 0.64095 | 0.66916 | 0.84435 | 0.87608 | 0.40161 | 0.50684 |
| 5 | userid | 1003 | 0 | 1.60000 | 1.21283 | 0.76564 | 0.32802 | 0.95867 | 0.87070 | -1.10020 | -0.19762 | -0.01482 | 0.27210 |
| 6 | userid | 1004 | 0 | -0.49231 | 1.49887 | 0.35442 | -0.42536 | -0.81954 | 0.16064 | 0.75299 | 1.16448 | 1.15989 | -0.20263 |
| 7 | userid | 1005 | 0 | -1.23826 | 0.41080 | 1.22775 | -0.10516 | 1.22577 | 0.66090 | -0.68936 | 1.03052 | -0.02753 | 1.18236 |
| 8 | userid | 1006 | 0 | 1.23899 | 0.76251 | -0.88248 | 0.25218 | 0.31963 | 0.73810 | 0.53201 | 0.86575 | 0.08586 | 0.28507 |
| 9 | userid | 1007 | 0 | 0.18701 | 0.45893 | 0.35841 | -0.27636 | -0.55479 | 0.10880 | 0.46377 | 0.55028 | 0.93723 | -0.80036 |
| 10 | userid | 1008 | 0 | -0.48266 | 0.11643 | -0.00731 | 0.77633 | 0.51574 | 0.52587 | -0.54637 | 1.02321 | 0.41732 | 0.43073 |
The following statements print the last 10 observations in the factorsOut data table, which includes some of the rows that are related to the latent factors for items. The output is shown in Output 33.1.2.
data _null_;
if 0 then set mycas.factorsOut nobs=n;
call symputx("n",left(put(n,best.)),'l');
run;
proc print data=mycas.factorsOut(firstobs=%eval(&n-10));
run;
Output 33.1.2: Factors
| Obs | Variable | Level | Bias | Factor1 | Factor2 | Factor3 | Factor4 | Factor5 | Factor6 | Factor7 | Factor8 | Factor9 | Factor10 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 5530 | itemid | 56 | 0 | -0.18407 | -1.01744 | -0.63280 | -2.90885 | -1.40714 | -0.33733 | 1.99937 | -1.11106 | -1.19087 | -0.54071 |
| 5531 | itemid | 60 | 0 | -0.14204 | -0.45022 | -1.19370 | -2.60695 | -1.23928 | -1.58881 | 0.01273 | -0.29118 | 0.63390 | -1.83230 |
| 5532 | itemid | 89 | 0 | 1.12289 | -1.16811 | -0.04444 | -0.99465 | 1.04710 | -2.50855 | 1.14419 | 0.89997 | 0.09599 | 1.29834 |
| 5533 | itemid | 113 | 0 | -0.33604 | -2.17536 | 0.27534 | 0.67900 | -2.57584 | -0.50169 | 1.28195 | -1.31917 | -0.58419 | 1.98762 |
| 5534 | itemid | 127 | 0 | -0.37295 | -2.37290 | -1.32851 | 1.07461 | 0.12567 | 0.46562 | 1.19621 | 0.69504 | -1.42968 | -1.52567 |
| 5535 | itemid | 131 | 0 | 0.15032 | -2.69967 | 0.09119 | -1.10570 | -0.41368 | -1.37352 | 0.52750 | -0.29410 | -0.37334 | -2.98499 |
| 5536 | itemid | 136 | 0 | 0.79232 | -1.41010 | -1.47762 | -1.62906 | -0.22300 | -1.78348 | 1.25377 | -1.35561 | -0.82134 | -0.96098 |
| 5537 | itemid | 153 | 0 | 0.85729 | 0.51769 | -1.76106 | -1.14285 | 0.07401 | -1.05292 | 1.08407 | -0.56030 | -1.83266 | 0.12960 |
| 5538 | itemid | 184 | 0 | 0.19092 | -0.13800 | -0.66986 | -2.12776 | -0.81316 | -1.19575 | 1.66791 | -1.17741 | -1.87976 | -0.75463 |
| 5539 | itemid | 186 | 0 | 2.95957 | 0.22948 | 1.67505 | 1.93499 | 0.20844 | 1.72228 | 0.18481 | -1.09187 | 0.18811 | 1.95087 |
| 5540 | itemid | 194 | 0 | 1.05736 | 0.73089 | 0.22407 | -2.10187 | -0.09919 | 0.58072 | 2.60663 | -0.65904 | -1.79021 | -0.11884 |
You can use the factorsOut output table to rank items for each user. The following code shows how to how to find the top three items for a sample user (that is, the one whose user ID is 6313).
First, you create the scoring data table that includes the user ID of interest:
data mycas.user6313;
input userid;
datalines;
6313
;
run;
Next, you use the ASTORE procedure to score this user:
proc astore;
setoption REC_TOP_N 3;
score data=mycas.user6313 rstore=mycas.savestatefile out=mycas.rankedItems;
run;
quit;
The following statements print the top three recommended items for user 6313. The output is shown in Output 33.1.3. Note: The itemid column name in the analytic store scoring table has been changed from the previous release. It now has the prefix _RECOMMENDED_.
proc print data=mycas.rankedItems;
run;
Output 33.1.3: Top Three Items for User 6313
| Obs | userid | _RECOMMENDED_itemid | _RANK | _SCORE |
|---|---|---|---|---|
| 1 | 6313 | 15 | 1 | 8.22146 |
| 2 | 6313 | 16 | 2 | 8.13729 |
| 3 | 6313 | 41 | 3 | 6.62799 |
Running the recBpr Action on User Community Website Data
This section contains Lua code for the analysis in the CASL version of this example, which contains details about the results.
Note: In order to run this code, the data that are described in the CASL version need to be accessible to the CAS server. One way to do this is to convert the usersCommunity data to the comma-separated-value (CSV) file usersCommunity.csv and then use the following code to load the CSV file into CAS:
s:loadtable{casLib="casuser", path="usersCommunity.csv"}
For more information about coding in Lua, see Getting Started with SAS Viya for Lua and SAS Viya: System Programming Guide.
The following statements train a Bayesian personalized ranking model on the usersCommunity data by using the recBpr action:
s:loadactionset{actionset="recommenderEngine"}
s:recBpr{table={name="data.usersCommunity"},
inputs={"userid", "itemid"},
nominals={"userid", "itemid"},
userId="userid",
itemId="itemid",
maxIter=20, nFactors=10, learnStep=0.01, regularization=0.01,
outModel={name="factorsOut"}}
Running the recBpr Action on User Community Website Data
This section contains Python code for the analysis in the CASL version of this example, which contains details about the results.
Note: In order to run this code, the data that are described in the CASL version need to be accessible to the CAS server. One way to do this is to convert the usersCommunity data to the comma-separated-value (CSV) file usersCommunity.csv and then use the following code to load the CSV file into CAS:
s.upload_file('usersCommunity.csv')
For more information about coding in Python, see Getting Started with SAS Viya for Python and SAS Viya: System Programming Guide.
The following statements train a Bayesian personalized ranking model on the usersCommunity data by using the recBpr action:
s.loadactionset{actionset="recommenderEngine"}
s.recBpr(display={"names":{"DescStatsInt","FinalLoss","ModelInfo",
"NObs","OptIterHistory "}},
userId="userid",
itemId="itemid",
inputs={"userid","itemid"},
nominals={"userid","itemid"},
outModel={"name":"factorsOut", "replace":True},
learnStep=0.01, maxIter=20, nFactors=10, regularization=0.01,
table={"caslib":"hps", "name":"usersCommunity"})
Running the recBpr Action on User Community Website Data
This section contains R code for the analysis in the CASL version of this example, which contains details about the results.
Note: In order to run this code, the data that are described in the CASL version need to be accessible to the CAS server. One way to do this is to convert the usersCommunity data to the comma-separated-value (CSV) file usersCommunity.csv and then use the following code to load the CSV file into CAS:
m <- cas.read.csv(s, "usersCommunity.csv", casOut=list(name="usersCommunity"))
For more information about coding in R, see Getting Started with SAS Viya for R and SAS Viya: System Programming Guide.
The following statements train a Bayesian personalized ranking model on the usersCommunity data by using the recBpr action:
ds <- cas.read.table(s,
"u.data",
header = FALSE,
col.names = c("userid", "itemid"),
casOut = list(name = "usersCommunity",replace = TRUE))
loadActionSet(s,'recommenderEngine')
rs <- cas.recBpr.recBpr(s,
table = list(name = "usersCommunity"),
outModel = list(name = "factorsOut", replace = TRUE),
inputs = list("userid", "itemid"),
nominals = list("userid", "itemid"),
userId = "userid",
itemId = "itemid",
maxIter = 20,
nFactors = 10,
learnStep = 0.01,
regularization = 0.01
)