2015-01-05 2 views
10

मैं प्रोटोटाइप अनुशंसा प्रणाली बनाने के लिए स्पार्क की mllib.recommendation लाइब्रेरी का उपयोग करना चाहता हूं।mllib.recommendation का उपयोग कैसे करें यदि उपयोगकर्ता आईडी संगत पूर्णांक के बजाय स्ट्रिंग हैं?

AB123XY45678 
CD234WZ12345 
EF345OOO1234 
GH456XY98765 
.... 

मैं mllib.recommendation पुस्तकालय का उपयोग करने, Rating वर्ग के एपीआई के अनुसार चाहते हैं, उपयोगकर्ता आईडी पूर्णांक होना है (हालांकि, उपयोगकर्ता डेटा मैं का प्रारूप निम्न स्वरूप के बारे में कुछ है भी संगत होना चाहिए?)

यह वास्तविक उपयोगकर्ता आईडी के बीच किसी प्रकार का रूपांतरण दिखता है और स्पार्क द्वारा उपयोग किए जाने वाले संख्यात्मक लोगों को किया जाना चाहिए। लेकिन मुझे यह कैसे करना चाहिए?

उत्तर

10

स्पार्क को वास्तव में संख्यात्मक आईडी की आवश्यकता नहीं है, इसे केवल कुछ अद्वितीय मूल्य प्राप्त करने की आवश्यकता है, लेकिन कार्यान्वयन के लिए उन्होंने Int को चुना।

आप userId के लिए सरल आगे पीछे परिवर्तन कर सकते हैं:

case class MyRating(userId: String, product: Int, rating: Double) 

    val data: RDD[MyRating] = ??? 

    // Assign unique Long id for each userId 
    val userIdToInt: RDD[(String, Long)] = 
    data.map(_.userId).distinct().zipWithUniqueId() 

    // Reverse mapping from generated id to original 
    val reverseMapping: RDD[(Long, String)] 
    userIdToInt map { case (l, r) => (r, l) } 

    // Depends on data size, maybe too big to keep 
    // on single machine 
    val map: Map[String, Int] = 
    userIdToInt.collect().toMap.mapValues(_.toInt) 

    // Transform to MLLib rating 
    val rating: RDD[Rating] = data.map { r => 
    Rating(userIdToInt.lookup(r.userId).head.toInt, r.product, r.rating) 
    // -- or 
    Rating(map(r.userId), r.product, r.rating) 
    } 

    // ... train model 

    // ... get back to MyRating userId from Int 

    val someUserId: String = reverseMapping.lookup(123).head 

तुम भी कोशिश कर सकते हैं 'data.zipWithUniqueId()' लेकिन मुझे यकीन है कि इस मामले में .toInt सुरक्षित परिवर्तन भी हो जाएगा नहीं कर रहा हूँ यदि डेटासेट आकार छोटा है।

+1

क्या यह प्रत्येक रेटिंग के लिए एक अद्वितीय अनुक्रमणिका असाइन नहीं करता है, न कि प्रत्येक उपयोगकर्ता? मुझे नहीं लगता कि यह काम करेगा यदि उपयोगकर्ता के पास कई रेटिंग हैं। – PBJ

+0

@ पीबीजे, हाँ, आप सही हैं, मैंने –

+1

'लुकअप' दृष्टिकोण में कोड अपडेट किया है, एक वैध स्पार्क कोड नहीं है। यह संकलित होगा लेकिन रनटाइम पर उड़ जाएगा। क्या आप इसे ठीक कर सकते हैं? – zero323

1

उपर्युक्त समाधान हमेशा की तरह काम नहीं करता है जैसा मैंने पाया था। स्पार्क आरडीडी के अन्य आरडीडी के भीतर से प्रदर्शन करने में सक्षम नहीं है। त्रुटि आउटपुट:

org.apache.spark.SparkException: RDD परिवर्तनों और कार्यों कर सकते हैं केवल किया, अन्य परिवर्तनों के अंदर नहीं चालक द्वारा hereinvoked कोड दर्ज करें; उदाहरण के लिए, rdd1.map (x => rdd2.values.count() * x) अमान्य है क्योंकि मान परिवर्तन और गिनती कार्रवाई rdd1.map परिवर्तन के अंदर निष्पादित नहीं की जा सकती है। अधिक जानकारी के लिए, SPARK-5063 देखें।

एक समाधान के रूप में आप उपयोगकर्ता आईडी और अद्वितीय आईडी के बीच संबंध को स्टोर करने के लिए मूल डेटा आरडीडी के साथ उपयोगकर्ता IDToInt RDD में शामिल हो सकते हैं। फिर बाद में आप इस आरडीडी के साथ आरडीडी के परिणामों में शामिल हो सकते हैं।

// Create RDD with the unique id included 
val dataWithUniqueUserId: RDD[(String, Int, Int, Double)] = 
    data.keyBy(_.userId).join(userIdToInt).map(r => 
     (r._2._1.userId, r._2._2.toInt, r._2._1.productId, 1)) 
3

स्ट्रिंग को अद्वितीय पूर्णांक अनुक्रमणिका में बदलने के लिए आपको अपने उपयोगकर्ता आईडी में स्ट्रिंगइंडेक्सर चलाने की आवश्यकता है। उन्हें लगातार नहीं होना चाहिए।

हम में https://www.aihello.com

df है हमारे आइटम सिफारिश इंजन के लिए इसका उपयोग (उपयोगकर्ता: स्ट्रिंग, उत्पाद, रेटिंग)

val stringindexer = new StringIndexer() 
     .setInputCol("user") 
     .setOutputCol("userNumber") 
    val modelc = stringindexer.fit(df) 
    val df = modelc.transform(df) 
1

@Ganesh कृष्णन सही है, StringIndexer इस समस्या का समाधान।

from pyspark.ml.feature import OneHotEncoder, StringIndexer 
from pyspark.sql import SQLContext 
>>> spark = SQLContext(sc)                    
>>> df = spark.createDataFrame(
...  [(0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c")], 
...  ["id", "category"]) 

| id|category| 
+---+--------+ 
| 0|  a| 
| 1|  b| 
| 2|  c| 
| 3|  a| 
| 4|  a| 
| 5|  c| 
+---+--------+ 
>>> stringIndexer = StringIndexer(inputCol="category", outputCol="categoryIndex") 
>>> model = stringIndexer.fit(df) 
>>> indexed = model.transform(df) 
>>> indexed.show() 
+---+--------+-------------+ 
| id|category|categoryIndex| 
+---+--------+-------------+ 
| 0|  a|   0.0| 
| 1|  b|   2.0| 
| 2|  c|   1.0| 
| 3|  a|   0.0| 
| 4|  a|   0.0| 
| 5|  c|   1.0| 
+---+--------+-------------+ 

>>> converter = IndexToString(inputCol="categoryIndex", outputCol="originalCategory") 
>>> converted = converter.transform(indexed) 
>>> converted.show() 
+---+--------+-------------+----------------+ 
| id|category|categoryIndex|originalCategory| 
+---+--------+-------------+----------------+ 
| 0|  a|   0.0|    a| 
| 1|  b|   2.0|    b| 
| 2|  c|   1.0|    c| 
| 3|  a|   0.0|    a| 
| 4|  a|   0.0|    a| 
| 5|  c|   1.0|    c| 
+---+--------+-------------+----------------+ 

>>> converted.select("id", "originalCategory").show() 
+---+----------------+ 
| id|originalCategory| 
+---+----------------+ 
| 0|    a| 
| 1|    b| 
| 2|    c| 
| 3|    a| 
| 4|    a| 
| 5|    c| 
+---+----------------+ 
संबंधित मुद्दे