2013-03-26 40 views
5

Tôi đang sử dụng Weka in Scala (mặc dù cú pháp hầu như giống hệt với Java). Tôi đang cố gắng để đánh giá dữ liệu của tôi với một clusterer SimpleKMeans, nhưng clusterer sẽ không chấp nhận dữ liệu chuỗi. Tôi không muốn cụm vào dữ liệu chuỗi; Tôi chỉ muốn sử dụng nó để gắn nhãn các điểm.Weka, SimpleKMeans không thể xử lý các thuộc tính chuỗi

Đây là dữ liệu tôi đang sử dụng:

@relation Locations 
@attribute ID string 
@attribute Latitude numeric 
@attribute Longitude numeric 
@data 
'Carnegie Mellon University', 40.443064, -79.944163 
'Stanford University', 37.427539, -122.170169 
'Massachusetts Institute of Technology', 42.358866, -71.093823 
'University of California Berkeley', 37.872166, -122.259444 
'University of Washington', 47.65601, -122.30934 
'University of Illinois Urbana Champaign', 40.091022, -88.229992 
'University of Southern California', 34.019372, -118.28611 
'University of California San Diego', 32.881494, -117.243079 

Như bạn có thể thấy, đó là bản chất là một tập hợp các điểm trên một x và y phối hợp máy bay. Giá trị của bất kỳ mẫu nào là không đáng kể; đây chỉ đơn giản là một bài tập trong làm việc với Weka.

Đây là mã được đem lại cho tôi rắc rối:

val instance = new Instances(new StringReader(wekaHeader + wekaData)) 

val simpleKMeans = new SimpleKMeans() 
simpleKMeans.buildClusterer(instance) 

val eval = new ClusterEvaluation() 
eval.setClusterer(simpleKMeans) 
eval.evaluateClusterer(new Instances(instance)) 

Logger.info(eval.clusterResultsToString) 

tôi nhận được lỗi sau trên simpleKMeans.buildClusterer(instance):

[UnsupportedAttributeTypeException: weka.clusterers.SimpleKMeans: Không thể xử lý các thuộc tính chuỗi]

Làm cách nào để Weka giữ lại ID trong khi thực hiện phân cụm?


Dưới đây là một vài bước khác mà tôi đã thực hiện để khắc phục sự cố này:

tôi đã sử dụng Weka Explorer và nạp dữ liệu này như một CSV:

ID, Latitude, Longitude 
'Carnegie Mellon University', 40.443064, -79.944163 
'Stanford University', 37.427539, -122.170169 
'Massachusetts Institute of Technology', 42.358866, -71.093823 
'University of California Berkeley', 37.872166, -122.259444 
'University of Washington', 47.65601, -122.30934 
'University of Illinois Urbana Champaign', 40.091022, -88.229992 
'University of Southern California', 34.019372, -118.28611 
'University of California San Diego', 32.881494, -117.243079 

này làm những gì tôi muốn nó làm trong Weka Explorer. Weka nhóm các điểm và giữ lại cột ID để xác định mỗi điểm. Tôi sẽ làm điều này trong mã của tôi, nhưng tôi đang cố gắng để làm điều này mà không tạo ra các tập tin bổ sung. Như bạn có thể thấy từ số Weka Java API, Instances diễn giải một số java.io.Reader chỉ dưới dạng ARFF.

Tôi cũng đã thử đoạn mã sau:

val instance = new Instances(new StringReader(wekaHeader + wekaData)) 
instance.deleteAttributeAt(0) 

val simpleKMeans = new SimpleKMeans() 
simpleKMeans.buildClusterer(instance) 

val eval = new ClusterEvaluation() 
eval.setClusterer(simpleKMeans) 
eval.evaluateClusterer(new Instances(instance)) 

Logger.info(eval.clusterResultsToString) 

này hoạt động trong mã của tôi, và hiển thị kết quả. Điều đó chứng minh rằng Weka đang làm việc nói chung, nhưng vì tôi đang xóa thuộc tính ID, tôi thực sự không thể ánh xạ các điểm được nhóm lại trên các giá trị ban đầu.

+0

Tôi nghĩ rằng ID của bạn được chuyển đổi thành một thuộc tính danh nghĩa khi tải từ một CSV. Một điều bạn có thể thử là đặt thuộc tính ID làm thuộc tính lớp. Hoặc tự chuyển đổi nó thành một loại danh nghĩa. – Sentry

+0

Cảm ơn @Sentry, tôi có thể xác nhận điều đó là chính xác. Tôi đã đăng một câu trả lời với những gì tôi đã học về nó. –

Trả lời

5

tôi trả lời câu hỏi của riêng tôi, và khi làm như vậy, có hai vấn đề mà tôi muốn đến địa chỉ:

  • Tại sao CSV làm việc với chuỗi giá trị
  • Làm thế nào để có được thông tin cụm từ cụm đánh giá

Như Sentry chỉ ra trong các ý kiến, ID nào trong thực tế được chuyển đổi sang một danh nghĩa thuộc tính khi được tải từ CSV.

Nếu dữ liệu phải nằm trong một định dạng ARFF (như trong ví dụ của tôi, nơi các đối tượng Instances được tạo ra từ một StringReader), sau đó các bộ lọc StringToNominal thể được áp dụng:

val instances = new Instances(new StringReader(wekaHeader + wekaData)) 

    val filter = new StringToNominal() 
    filter.setAttributeRange("first") 
    filter.setInputFormat(instances) 

    val filteredInstance = Filter.useFilter(instances, filter) 

    val simpleKMeans = new SimpleKMeans() 
    simpleKMeans.buildClusterer(instance) 
    ... 

Điều này cho phép "chuỗi Giá trị " được sử dụng trong phân cụm, mặc dù nó thực sự chỉ được coi là giá trị danh nghĩa. Nó không ảnh hưởng đến việc phân cụm (nếu ID là duy nhất), nhưng nó không góp phần vào việc đánh giá như tôi đã hy vọng, điều này đưa tôi đến vấn đề tiếp theo.


Tôi đã hy vọng để có thể có được một bản đồ tốt đẹp của cluster và dữ liệu, như cluster: Int -> Array[(ID, latitude, longitude)] hoặc ID -> cluster: Int. Tuy nhiên, kết quả cụm không thuận tiện. Theo kinh nghiệm của tôi trong vài ngày qua, có hai cách tiếp cận có thể được sử dụng để tìm cụm của mỗi điểm dữ liệu.

Để nhận phân bổ cụm, simpleKMeans.getAssignments trả về một mảng các số nguyên là phân bổ cụm cho mỗi phần tử dữ liệu. Mảng các số nguyên nằm trong cùng thứ tự với các mục dữ liệu gốc và phải được liên kết theo cách thủ công với các mục dữ liệu gốc. Điều này có thể dễ dàng thực hiện ở Scala bằng cách sử dụng phương thức zip trên danh sách dữ liệu ban đầu và sau đó sử dụng các phương pháp khác như groupBy hoặc map để lấy bộ sưu tập ở định dạng yêu thích của bạn. Hãy nhớ rằng phương pháp này không sử dụng thuộc tính ID tại tất cả và thuộc tính ID có thể được bỏ qua khỏi các điểm dữ liệu hoàn toàn.

Tuy nhiên, bạn cũng có thể nhận các trung tâm cụm với simpleKMeans.getClusterCentroids hoặc eval.clusterResultsToString(). Tôi đã không sử dụng điều này rất nhiều, nhưng nó dường như với tôi rằng thuộc tính ID có thể được phục hồi từ các trung tâm cụm ở đây. Theo như tôi có thể nói, đây là tình huống duy nhất mà dữ liệu ID có thể được sử dụng hoặc phục hồi từ việc đánh giá cụm.

0

Tôi gặp lỗi tương tự khi có giá trị Chuỗi trong một dòng trong tệp CSV có vài triệu hàng. Đây là cách tôi đã tìm ra dòng nào có giá trị chuỗi.

Ngoại lệ "Không thể xử lý thuộc tính chuỗi!" không đưa ra bất kỳ đầu mối nào về số dòng. Do đó:

  • Tôi đã nhập tệp CSV vào giao diện Weka Explorer và tạo tệp * .arff.
  • Sau đó, thay đổi theo cách thủ công loại từ chuỗi thành số trong tệp * .arrf ở đầu như hiển thị bên dưới.
  • Sau đó tôi đã cố gắng xây dựng cụm bằng tệp * .arff.
  • Tôi nhận được số dòng chính xác như một phần của ngoại lệ
  • Tôi đã xóa dòng khỏi tệp * .arff và tải lại. Nó hoạt động mà không có bất kỳ vấn đề gì.

Chuỗi được chuyển đổi -> số trong *.tập tin arff

@attribute total numeric 
@attribute avgDailyMB numeric 
@attribute mccMncCount numeric 
@attribute operatorCount numeric 
@attribute authSuccessRate numeric 
@attribute totalMonthlyRequets numeric 
@attribute tokenCount numeric 
@attribute osVersionCount numeric 
@attribute totalAuthUserIds numeric 
@attribute makeCount numeric 
@attribute modelCount numeric 
@attribute maxDailyRequests numeric 
@attribute avgDailyRequests numeric 

Lỗi báo cáo dòng con số chính xác

java.io.IOException: number expected, read Token[value.total], line 1750464 
    at weka.core.converters.ArffLoader$ArffReader.errorMessage(ArffLoader.java:354) 
    at weka.core.converters.ArffLoader$ArffReader.getInstanceFull(ArffLoader.java:728) 
    at weka.core.converters.ArffLoader$ArffReader.getInstance(ArffLoader.java:545) 
    at weka.core.converters.ArffLoader$ArffReader.readInstance(ArffLoader.java:514) 
    at weka.core.converters.ArffLoader$ArffReader.readInstance(ArffLoader.java:500) 
    at weka.core.Instances.<init>(Instances.java:138) 
    at com.lokendra.dissertation.ModelingUtils.kMeans(ModelingUtils.java:50) 
    at com.lokendra.dissertation.ModelingUtils.main(ModelingUtils.java:28) 
Các vấn đề liên quan