lolamontes69

Ch6 Ex7a-Programming Collective Intelligence

Jul 21st, 2013
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.68 KB | None | 0 0
  1. """ Chapter 6 Exercise 7a: Neural network classifier.
  2.  
  3.    Modify the neural network from Chapter 4 to be used for document classification. How do its results compare?
  4.  
  5.    This version of the neural net works but as it grows larger, it slows down (after about 20 trainquery() calls it starts to be longer than a minute per call), because it has to update every node in the db. The answer to this is to be selective in adding features, only adding known specifics to save time.(Or using a faster db.) Resultwise it learns pretty well.
  6.    """
  7.  
  8. from math import tanh
  9. from pysqlite2 import dbapi2 as sqlite
  10. import re as re
  11. import feedparser as feedparser
  12. from string import punctuation
  13.  
  14. def dtanh(y):
  15.     return 1.0-y*y
  16.  
  17. def sampletrain(cl):
  18.     cl.trainquery(['Nobody','owns','the','water'],['good','bad'],'good')
  19.     cl.trainquery(['the','quick','rabbit','jumps','fences'],['good','bad'],'good')
  20.     cl.trainquery(['buy','pharmeceuticals','now'],['good','bad'],'bad')
  21.     cl.trainquery(['make','quick','money','at','the','online','casino'],['good','bad'],'bad')
  22.     cl.trainquery(['the','quick','brown','fox','jumps','over','the','lazy','dog'],['good','bad'],'good')
  23.  
  24.  
  25. class searchnet:
  26.     def __init__(self,dbname):
  27.         self.con=sqlite.connect(dbname)
  28.  
  29.     def __del__(self):
  30.         self.con.close()
  31.  
  32.     def maketables(self):
  33.         self.con.execute('create table hiddennode(create_key)')
  34.         self.con.execute('create table feathidden(fromid,toid,strength)')
  35.         self.con.execute('create table hiddencat(fromid,toid,strength)')
  36.         self.con.commit()
  37.  
  38.     def getstrength(self,fromid,toid,layer):
  39.         if layer==0:
  40.             table='feathidden'
  41.             res=self.con.execute('select strength from %s where fromid="%s" and toid=%d' % (table,fromid,toid)).fetchone()
  42.         else:
  43.             table='hiddencat'
  44.             res=self.con.execute('select strength from %s where fromid=%d and toid="%s"' % (table,fromid,toid)).fetchone()
  45.         if res==None:
  46.             if layer==0: return -0.2
  47.             if layer==1: return 0
  48.         return res[0]
  49.  
  50.     def setstrength(self,fromid,toid,layer,strength):
  51.         if layer==0:
  52.             table='feathidden'
  53.             res=self.con.execute("select rowid from %s where fromid='%s' and toid=%d" % (table,fromid,toid)).fetchone()
  54.         else:
  55.             table='hiddencat'
  56.             res=self.con.execute('select rowid from %s where fromid=%d and toid="%s"' % (table,fromid,toid)).fetchone()
  57.         if res==None:
  58.             if table=='feathidden':
  59.                 self.con.execute('insert into %s (fromid,toid,strength) values ("%s",%d,%f)' % (table,fromid,toid,strength))
  60.             elif table=='hiddencat':
  61.                 self.con.execute('insert into %s (fromid,toid,strength) values (%d,"%s",%f)' % (table,fromid,toid,strength))
  62.         else:
  63.             rowid=res[0]
  64.             self.con.execute('update %s set strength=%f where rowid=%d' % (table,strength,rowid))
  65.  
  66.     def generatehiddennode(self,featids,catids):
  67. #        if len(featids)>3: return None
  68.         # Check if we already created a node for this set of words
  69.         try:
  70.             createkey='_'.join(sorted([str(wi).encode('utf-8') for wi in featids]))
  71.             res=self.con.execute("select rowid from hiddennode where create_key='%s'" % createkey).fetchone()
  72.         except: return
  73.         # If not create it
  74.         if res==None:
  75.             cur=self.con.execute("insert into hiddennode (create_key) values ('%s')" % createkey)
  76.             hiddenid=cur.lastrowid
  77.             # Put in some default weights
  78.             for featid in featids:
  79.                 self.setstrength(featid,hiddenid,0,1.0/len(featids))
  80.             for catid in catids:
  81.                 self.setstrength(hiddenid,catid,1,0.1)
  82.             self.con.commit()
  83.  
  84.     def getallhiddenids(self,featids,catids):
  85.         l1={}
  86.         for featid in featids:
  87.             cur=self.con.execute('select toid from feathidden where fromid="%s"' % featid)
  88.             for row in cur: l1[row[0]]=1
  89.         for catid in catids:
  90.             cur=self.con.execute('select fromid from hiddencat where toid="%s"' % catid)
  91.             for row in cur: l1[row[0]]=1
  92.         return l1.keys()
  93.  
  94.     def setupnetwork(self,featids,catids):
  95.         # Value lists
  96.         self.featids=featids
  97.         self.hiddenids=self.getallhiddenids(featids,catids)
  98.         self.catids=catids
  99.  
  100.         # Node outputs         strengths set to default values
  101.         self.ai = [1.0]*len(self.featids)
  102.         self.ah = [1.0]*len(self.hiddenids)
  103.         self.ao = [1.0]*len(self.catids)
  104.  
  105.         # Create weights matrix
  106.         self.wi =[[self.getstrength(featid,hiddenid,0) for hiddenid in self.hiddenids] for featid in self.featids]
  107.         self.wo =[[self.getstrength(hiddenid,catid,1) for catid in self.catids] for hiddenid in self.hiddenids]
  108.  
  109.     def feedforward(self):
  110.         # the only inputs are the query words
  111.         for i in range(len(self.featids)):
  112.             self.ai[i] = 1.0
  113.  
  114.         # hidden activations
  115.         for j in range(len(self.hiddenids)):
  116.             sum = 0.0
  117.             for i in range(len(self.featids)):
  118.                 sum = sum + self.ai[i] * self.wi[i][j]
  119.             self.ah[j] = tanh(sum)
  120.  
  121.         # output activations
  122.         for k in range(len(self.catids)):
  123.             sum = 0.0
  124.             for j in range(len(self.hiddenids)):
  125.                 sum = sum + self.ah[j] * self.wo[j][k]
  126.             self.ao[k] = tanh(sum)
  127.  
  128.         return self.ao[:]
  129.  
  130.     def getresult(self,featids,catids):
  131.         self.setupnetwork(featids,catids)
  132.         return self.feedforward()
  133.  
  134.     def backPropagate(self,targets, N=0.5):
  135.         # calculate errors for output
  136.         output_deltas = [0.0]*len(self.catids)
  137.         for k in range(len(self.catids)):
  138.             error = targets[k]-self.ao[k]
  139.             output_deltas[k] = dtanh(self.ao[k])*error
  140.  
  141.         # calculate errors for hidden layer
  142.         hidden_deltas = [0.0]*len(self.hiddenids)
  143.         for j in range(len(self.hiddenids)):
  144.             error = 0.0
  145.             for k in range(len(self.catids)):
  146.                 error = error+output_deltas[k]*self.wo[j][k]
  147.             hidden_deltas[j] = dtanh(self.ah[j])*error
  148.  
  149.         # update output weights
  150.         for j in range(len(self.hiddenids)):
  151.             for k in range(len(self.catids)):
  152.                 change=output_deltas[k]*self.ah[j]
  153.                 self.wo[j][k] = self.wo[j][k] + N*change
  154.  
  155.         # update input weights
  156.         for i in range(len(self.featids)):
  157.             for j in range(len(self.hiddenids)):
  158.                 change = hidden_deltas[j]*self.ai[i]
  159.                 self.wi[i][j] = self.wi[i][j] + N*change
  160.  
  161.     def trainquery(self,featids,catids,selectedurl):
  162.         # generate a hiddennode if neccessary
  163.         self.generatehiddennode(featids,catids)
  164.  
  165.         self.setupnetwork(featids,catids)
  166.         self.feedforward()
  167.         targets=[0.0]*len(catids)
  168.         targets[catids.index(selectedurl)]=1.0
  169.         error = self.backPropagate(targets)
  170.         self.updatedatabase()
  171.  
  172.     def updatedatabase(self):
  173.         # set them to database values
  174.         for i in range(len(self.featids)):
  175.             for j in range(len(self.hiddenids)):
  176.                 self.setstrength(self.featids[i],self.hiddenids[j],0,self.wi[i][j])
  177.         for j in range(len(self.hiddenids)):
  178.             for k in range(len(self.catids)):
  179.                 self.setstrength(self.hiddenids[j],self.catids[k],1,self.wo[j][k])
  180.         self.con.commit()
  181.  
  182.     def guess_category(self,featurelist,catlist1):
  183.         if len(catlist1)==0:
  184.             list1=[]
  185.             return list1.append('none')
  186.         else: return self.getresult(featurelist,catlist1)
  187.  
  188.     def readentryfeatures(self,feed):
  189.         # Get feed entries and loop over them
  190.         splitter = re.compile('\\W*')
  191.         f=feedparser.parse(feed)
  192.         for entry in f['entries']:
  193.             print '\n-----'
  194.             # Print the contents of the entry
  195.             print 'Title:     '+entry['title'].encode('utf-8')
  196.             print 'Publisher  '+entry['publisher'].encode('utf-8')
  197.             print
  198.             print entry['summary'].encode('utf-8')
  199.             summarywords = entry['summary'].split(' ')
  200.  
  201.             featurelist = []
  202.             # Extract the title words and annotate
  203.             titlewords = [s.lower() for s in splitter.split(entry['title']) if len(s) > 2 and len(s) < 20]
  204.  
  205.             # Extract the summary words
  206.             summarywords = [s for s in splitter.split(entry['summary']) if len(s) > 2 and len(s) < 20]
  207.  
  208.             featurelist += titlewords + summarywords
  209.             featurelist.append('Publisher:'+ entry['publisher'])
  210.             uc = 0
  211.             for i in range(len(summarywords)):
  212.                 w = summarywords[i]
  213.                 for p in punctuation:
  214.                     if p in w: w = w.replace(p,"")
  215.                 if (w.isupper()):
  216.                     uc += 1
  217.                 featurelist.append(w.lower())
  218.                 if i < len(summarywords) - 1:
  219.                     twowords = summarywords[i].encode('utf-8')+' '+summarywords[i+1].encode('utf-8')   # Get word pairs in summary as features
  220.                     featurelist.append(twowords.lower())
  221.                     if (float(uc) / len(summarywords) > 0.3):
  222.                         featurelist.append('UPPERCASE')
  223.  
  224.             # Convert to list of features here
  225.             catlist1=[]
  226.             # Fetch a list of categories
  227.             for c in self.con.execute('select distinct toid from hiddencat'): catlist1.append(c[0])
  228.             # Print the best guess at the current category
  229.             best = 0
  230.             bestguess = 'None'
  231.             catlist = self.guess_category(featurelist,catlist1)
  232.             if catlist==None: catlist=[]
  233.             for a in range(len(catlist)):
  234.                 if (best==0) and (float(catlist[a])<0):
  235.                     best = float(catlist[a])             # Else if all values < 0 ...
  236.                     bestguess = catlist1[a]              # The best one will not get chosen
  237.                 elif float(catlist[a]) > best:
  238.                     best = float(catlist[a])
  239.                     bestguess = catlist1[a]
  240.             print 'Guess: '+ bestguess
  241.  
  242.             # Ask the user to specify the correct category and train on that
  243.             cl=raw_input('Enter category: ')
  244.             if cl not in catlist1:
  245.                 catlist1.append(cl)
  246.             try:
  247.                 self.trainquery(featurelist,catlist1,cl)
  248.             except: print "\n---------Unable to train with this data----------\n"
  249.         self.con.commit()
  250.  
  251. """ Usage.
  252.  
  253. import ch6ex7 as nn
  254. mynet=nn.searchnet('nn.db')
  255. mynet.maketables()
  256. mynet.readentryfeatures('python_search.xml')
  257.  
  258. """
Advertisement
Add Comment
Please, Sign In to add comment