ConceptNET: fyrstu skrefin

Markmið: Að búa til lítið forrit notfærir sér ConceptNet til að greina innihald texta á ensku.
Forkröfur eru: grunnþekking á Java, XML og hlutbundinni forritun.
Tól sem þarf: Java SDK 1.4.2, ConceptNet, XML-RPC fyrir Java Jakarta-Commons-codec og einhvert þróunarumhverfi t.d. Eclipse
Áhugavert að skoða: Montylingua

ConceptNet er þekkingargrunnur (e. knowledge base) sem Media Lab við MIT hafa þróað. Fyrir þá sem ekki vita hvað þekkingargrunnur er þá er það í stuttu máli sérstök tegund gagnagrunna (e. database). Hvað ConceptNet varðar þá er það gagnagrunnur sem heldur utan um hugtök sem okkur sem manneskjum finnst sjálfsögð vitneskja eins og t.d. "það er mikið að borga 6000 krónur fyrir samloku" og "hundur er dýrategund". Eins kannski undarlega og það kann að hljóma fyrir sumum, þá hafa tölvur ekki þessa þekkingu "innbyggða". ConceptNet er búið til (þegar þetta er skrifað) út frá u.þ.b. 700 þúsund setningum frá rétt rúmlega 14 þúsund notendum sem komið hafa inn í gegnum Open Mind Common Sense Project. Svo við spáum aðeins meira í tölum þá mynda þessar setningar rétt um 1,6 milljón fullyrðingar um ýmsa hluti og hægt er að leita í þeim í ConceptNet þekkingargrunninum. Þeir sem vilja lesa nánar um ConceptNet geta nálgast þær upplýsingar hér.

Það sem við ætlum að skoða að þessu sinni er hvernig skrifa á forrit í Java sem talar við netþjón (e. server) XML skilaboðum. Þjónninn sem við tölum við notast við XML-RPC(e. XML-Remote Procedure Call). Hvar kemur þá ConceptNet inn í þetta allt saman? Við tölum aldrei beint við ConceptNet heldur köllum við á XML-RPC þjóininn sem sér svo um að kalla á ConceptNet. ConceptNet framkvæmir svo aðgerðina sem við báðum um og skilar niðurstöðunum til baka til XML-RPC sem svo skilar þeim til okkar. Ástæðan fyrir þessari hönnun er svo að auðvelt sé að breyta ConceptNet án þess að breyta þurfi forritunum sem nota hann. Einnig gerir þetta það að verkum að hægt er að tala við ConceptNet í hvaða forritunarmáli sem er, einu skilyrðin er að forritunarmálið sem notað er styðji XMLsamskipti. Þetta er allt voða flott ... en hvað getur svo ConceptNet gert? Til að svara þessari spurningu er langbest að taka dæmi. Segjum sem svo að við viljum fá að vita hvert umfjöllunarefni einhvers tiltekins text er. Þá sendum við textann yfir á XML-RPC netþjóninn. Hann spyr ConceptNet um innihald textans fær niðurstöður ef ConceptNet getur greint textann og sendir okkur þær svo til baka í formi XML. Fyrir þá sem vilja vita meira um XML-RPC þá er hægt að nálgast upplýsingar um það hér.

Það fyrsta sem við skoðum er hvernig við keyrum XML-RPC netþjóninn. Netþjónninn sjálfur er skrifaður í Python og til að keyra hann er nauðsynlegt að hafa Python uppsett á þeirri vél sem á að sjá um það. Hægt er að nálgast Python hér. Á heimasíðu Python er einnig sýnt hvernig á að setja Python upp. Þegar við höfum lokið við að setja upp Python þá er XML-RPC þjónninn ræstur með eftirfarandi skipun.

> runConceptNetServer.bat

ATH. ef þetta virkar ekki, getur virkað að keyra ConceptNetXMLRPCServer.py beint

Þessi netþjónn keyrir nú á porti (e. port) númer 8000 ef engum grunnstillingum hefur verið breytt. Ekki verður farið frekar í tölvusamskipti hér. Fyrir þá sem ekki eru vel að sér um helstu hugtökum sem snúa að því sviði þá er hægt að lesa sig til um það helsta hér.

Það var nefnt áðan að til þess að tala við ConceptNet þyrftum við að nota XML-RPC samskiptamátann. Það er rétt, en samt ekki alveg rétt. XML-RPC er eingöngu samskiptamáti en ekki raunveruleg skilaboð. Hvað þýðir það? Við getum litið á XML-RPC sem umslag og það er því augljóst að lítið gagn er í því að senda einhverjum umslag í pósti með engu innihaldi. Við eigum sem sagt eftir að búa til skilaboð sem fara í umslagið. Hvernig förum við eiginlega að því? Það er sáraeinfalt því við getum notað venjulega ensku til að spyrja grunninn um það sem við viljum vita. Venjulega ensku? Hvernig skilur þekkingargrunnurinn venjulega ensku? ConceptNet hefur innbyggt forrit sem sér um að breyta venjulegum enskum setningum í fyrirspurnir sem grunnurinn getur notað. Þetta innbyggað forrit nefnist Montylingua. Það er ekki nauðsynlegt að kunna skil á Montylingua til að geta notað það því að einu kröfurnar sem Montylingua gerir eru þær að notandinn kunni ensku.

Nú höfum við kynnt allt sem snýr að forritinu sem við ætlum að skrifa sem sér um að tala við ConceptNet netþjóninn.

Til að fá að vita hvaða föll og greiningaraðferðir ConceptNet netþjónninn býður upp á er langauðveldast að spyrja hann. Það getum við gert með því að opna einhver vefvafra (e. internet browser) t.d. Mozilla Firefox eða Internet Explorer og slá inn slóðina

http://localhost:8000

Þegar þetta hefur verið slegið inn í vafrann þá ætti að koma upp síða sem segir til um hvaða föll ConceptNet býður upp á. Hér fyrir neðan er listi yfir þau föll (og lýsinga rá þeim) sem birtast þegar netþjóninn er spurður í gegnum vafra.


apply_swaplist(text)

arg_grammar_accept_p(arg_chunked, re_pattern)

chunk(text)

chunk_and_lemmatise(text)

generate_extraction(text)
    -inputs a raw text document
    -outputs an extraction object which contains a
    parsed digest of the text
    -the extraction object can be passed as argument
    to methods jist_*()

guess_concept(text, simple_results_p=0)
    -inputs a raw text document
    - the input is an egocentric description where
    the subject is a mystery concept being described
    - for example: 'Foo is red and delicious. Foo
    spoils when it's been laid out too long. Foo has
    a stem and meat and skin.'
    - uses structure mapping similar to get_analogous_concepts()
    to guess what the mystery concept might be
    - the return type is the same as with get_analogous_concepts()
    - if simple_results_p = 1, then output object is simply
    a list of rank-ordered concepts

guess_mood(text)
    -inputs a raw text document
    -computes an affective classification of the document
    using paul ekman's six basic emotions
    - outputs the following six-tuple of pairs:
      (
       ('happy', 0.5),
       ('sad', 0.4),
       ('angry', 0.3),
       ('fearful', 0.9),
       ('disgusted', 0.0),
       ('surprised', 0.0),
      )
    - the cdr of each pair is a score in the range [0.0,1.0]
    representing the relative presence of that mood in the
    document

guess_topic(text, max_results=1000, flow_pinch=500, max_node_visits=1000)
    -inputs a raw text document
    - extracts events, adjectives, and things from text
    and finds their weighted contextual intersection
    - returns a pair whose car is a trace of the
    list of entities extracted from the text,
    and cdr are the results (in the same format as the
    return type of get_context)

jist_adjs(extraction)
    -inputs an extraction object
    -returns a list of all the adjectival phrases
    and modifiers in the extraction object

jist_entities(extraction)
    -inputs an extraction object
    -returns a list of all the noun chunks
    in the extraction object

jist_pxs(extraction)
    -inputs an extraction object
    -returns a list of all the prepositional phrases
    in the extraction object

jist_subj_events(extraction)
    -inputs an extraction object
    -returns entries like: ('I','read book')

jist_vsoos(extraction)
    -inputs an extraction object
    -returns a list of Verb-Subject-Object-Object
    tuples, each of the form: ('read','I','book','in bed')
    - all words are lemmatised, and semantically empty tokens
    are stripped (e.g.: the, a, modals)

lemmatise(text)
    -inputs a raw text document
    -outputs lemmatised text

parse_pred_arg(pp)
    parses the predicate-argument string
    returned by jist_predicates(), of the form:
    '("pred name" "arg 1" "arg 2" etc)'
    and returns them as a list

postchunk_px(chunked)

refine_arg(arg, re_pattern=None)

repair_arg(arg_chunked, re_pattern)

summarize_document(text, summary_size=5)
    inputs a raw text document
    outputs an algorithmically generated summary
    summary_size sets the size of the summary to generate,
    in sentences
    algorithm for summarization is:
    1) compute a document vector using guess_topic()
    2) compute sentence vectors using get_context()
    3) saliency is the strength of each sentence vector
    4) sentences are rank-ordered by saliency and pruned
    to summary size

system.listMethods()
    system.listMethods() => ['add', 'subtract', 'multiple']

    Returns a list of the methods supported by the server.

system.methodHelp(method_name)
    system.methodHelp('add') => "Adds two integers together"

    Returns a string containing documentation for the specified method.

system.methodSignature(method_name)
    system.methodSignature('add') => [double, int, int]

    Returns a list describing the signature of the method. In the
    above example, the add method takes two integers as arguments
    and returns a double result.

    This server does NOT support system.methodSignature.

tag(text)

unpp_predicate(pp_pred)

Í dæminu okkar ætlum við að notast við fallið guess_mood. Textinn sem verður notaður í dæminu er gefinn hér að neðan.

Lying awake at night I wipe the sweat from my brow
But it's not fear 'cos I'd rather go now
Trying to visualise the horrors that will lay ahead
The desert sand mound a burial ground

When it comes to the time
Are we partners in crime ?
When it comes to the time
We'll be ready to die

God let us go now and finish what's to be done
Thy Kingdom come
Thy shall be done... on earth

Trying to justify to ourselves the reasons to go
Should live and let live
Forget or forgive

But how can we let them go on this way ?
The reign of terror corruption must end
And we know deep down there's no other way
No trust, no reasoning, no more to say

Afraid to shoot strangers
Afraid to shoot strangers.

Fyrir þá sem ekki hafa áttað sig á því þá er þetta textinn við lagið Fear of the Dark með hljómsveitinni Iron Maiden.

Eins og alltaf í java forritum þá þurfum við að byrja á því að segja forritinu hvaða pakka við ætlum að nota. Ekki má gleyma því að vísa í xmlrpc bókasafnið og Jakarta commons safnið.

ATH þegar þetta er skrifað þá er conceptnet 2.1 nýjasta útgáfa og er lítilsháttar villa í því , þannig til að við getum notað miðlarann(e. server) í því, þurfum við að bæta einni skrá í rót conceptnet möppunar, hægt er að nálgast þessa skrá hér
import org.apache.xmlrpc.XmlRpcClient;
import org.apache.xmlrpc.XmlRpcException;

import java.util.Vector;

Inn í main fallið setjum við svo

try
{
    // búum til hlut til að tákna netþjóninn
    XmlRpcClient server = new XmlRpcClient( "http://localhost:8000" );

    // Búum til lista af breytum sem við ætlum að senda
    Vector params = new Vector();
    params.add( "Lying awake at night I wipe the sweat from my brow " +
                "But it's not fear 'cos I'd rather go now " +
                "Trying to visualise the horrors that will lay ahead " +
                "The desert sand mound a burial ground " +
                "When it comes to the time " +
                "Are we partners in crime ? " +
                "When it comes to the time " +
                "We'll be ready to die " +
                "God let us go now and finish what's to be done " +
                "Thy Kingdom come " +
                "Thy shall be done... on earth " +
                "Trying to justify to ourselves the reasons to go " +
                "Should live and let live " +
                "Forget or forgive " +
                "But how can we let them go on this way ? " +
                "The reign of terror corruption must end " +
                "And we know deep down there's no other way " +
                "No trust, no reasoning, no more to say " +
                "Afraid to shoot strangers " +
                "Afraid to shoot strangers. " );

    // segjum netþjóni að framkvæma aðgerðina guess_mood á gefnum færibreytum
    Vector result = (Vector)server.execute( "guess_mood", params );

    // prentum út niðurstöðurnar sem við fáum frá netþjóninum
    System.out.println( result );
}
catch ( XmlRpcException e )
{
    System.err.println( "Error-" + e.code + ": " + e );
    e.printStackTrace();
}
catch ( Exception e )
{
    System.err.println( "Error: " + e );
    e.printStackTrace();
}

Hér skilgreinum við hvaða þjón við ætlum að tala við og á hvaða porti, því næst smíðum við Vector sem heldur utan um þær færibreytur sem nauðsynlegar eru fyrir fallið sem kalla á í. Í okkar tilfelli er það einungis inntakið text sem við setjum í Vector-inn. Eftir að við höfum skilgreint netþjón og færibreytur þá biðjum við netþjóninn um að framkvæma aðgerðina guess_mood á þeim. Að því loknu prentum við svo út niðurstöðurnar á skjáinn.

[[disgusted, 0.13285266887944208], [fearful, 0.05904563061308537], [happy, 0.0], [sad, 0.0], [angry, 0.0], [surprised, 0.0]]

Niðurstöðurnar sem fást þegar forritið er keyrt eru þær að andrúmsloftið sem ConceptNet telur textann vera að lýsa eru disgusted og fearful.

Nú höfum við sýnt hvernig má á tiltöluega auðveldan hátt setja upp þekkingargrunn og smíða lítið forrit sem tala við hann. ConceptNet býður upp á ótal fleiri aðferðir við að sýna þekkingu og greina inntak en ekki verður farið í fleiri atriði að þessu sinni. Fyrir þá sem hafa áhuga á að skoða allann kóðann sem notaður var í þessu sýnidæmi, þá er hægt að nálgast hann hér.

 

CADIA
cadia@ru.is  |  Ofanleiti 2, IS -103 Reykjavík
Tel: +354 510 6427  |  Fax: +354 510 6201