public LinkClassifier backlinkTraining(HashMap<String, VSMElement> outlinkWeights)
            throws Exception {

        List<VSMElement> trainingSet = new ArrayList<VSMElement>();
        Tuple<String>[] tuples = graphRep.getHubGraph();
        for (int i = 0; i < tuples.length; i++) {
            String hubId = tuples[i].getKey();
            String[] outlinks = tuples[i].getValue().split("###");
            double totalProb = 0;
            for (int j = 0; j < outlinks.length; j++) {
                VSMElement elem = outlinkWeights.get(outlinks[j] + "_auth");
                if (elem != null) {
                    totalProb = totalProb + elem.getWeight();
                }
            }
            String url = graphRep.getHubURL(hubId);
            if (url != null && outlinks.length > 20) {
                LinkNeighborhood ln = graphRep.getBacklinkLN(new URL(url));
                if (ln != null) {
                    VSMElement elem =
                            new VSMElement(ln.getLink().toString() + ":::" + ln.getAroundString(),
                                    totalProb / outlinks.length);
                    trainingSet.add(elem);
                }
            }
        }
        System.out.println("TOTAL TRAINING:" + trainingSet.size());
		
		
        Collections.sort(trainingSet, VSMElement.DESC_ORDER_COMPARATOR);

        List<LinkNeighborhood> allLNs = new ArrayList<LinkNeighborhood>();
        for (int i = 0; i < trainingSet.size(); i++) {
            String[] parts = trainingSet.get(i).getWord().split(":::");
            LinkNeighborhood ln = new LinkNeighborhood(new URL(parts[0]));
            if (parts.length > 1) {
                StringTokenizer tokenizer = new StringTokenizer(parts[1], " ");
                Vector<String> aroundTemp = new Vector<String>();
                while (tokenizer.hasMoreTokens()) {
                    aroundTemp.add(tokenizer.nextToken());
                }
                String[] aroundArray = new String[aroundTemp.size()];
                aroundTemp.toArray(aroundArray);
                ln.setAround(aroundArray);
            }
            allLNs.add(ln);
        }

        // Sample the backlinks based on position in the list
        List<LinkNeighborhood> posSites = new ArrayList<LinkNeighborhood>();
        List<LinkNeighborhood> negSites = new ArrayList<LinkNeighborhood>();
        int sampleSize = Math.min(5000, allLNs.size() / 2);
        for (int i = 0; i < allLNs.size(); i++) {
            if (posSites.size() < sampleSize) {
                posSites.add(allLNs.get(i));
            }
        }
        for (int i = allLNs.size() - 1; i >= 0; i--) {
            if (negSites.size() < sampleSize) {
                negSites.add(allLNs.get(i));
            }
        }


        // TODO Following code is not really doing a sample, it's just converting it the lists in
        // Sampler objects to be compatible with createSmileInput method. Need to do some refactoring
        // in this whole class.
        List<Sampler<LinkNeighborhood>> instances = new ArrayList<Sampler<LinkNeighborhood>>(2);
        Sampler<LinkNeighborhood> posSamples = new Sampler<LinkNeighborhood>(posSites.size());
        Sampler<LinkNeighborhood> negSamples = new Sampler<LinkNeighborhood>(negSites.size());
        instances.add(posSamples);
        instances.add(negSamples);

        // Train actual classifier
        List<String> classValues = asList("POS", "NEG");
        LNClassifier classifier = classifierTrainer.trainLNClassifierBacklink(instances, classValues);

        return createLinkClassifierImpl("LinkClassifierHub", classifier);
    }
Loads training data to train the link classifier. The training data for each class were are
trying to predict is returned in a separate 'ordered' list. The position of the list
indicates the priority of the links in that list.

@param relevantUrls
@param levels
@return
@throws Exception
ache/src/main/java/achecrawler/link/classifier/builder/LinkClassifierBuilder.java