Practical Programming for NLP

This chapter is aimed at students and researchers who are eager to learn about practical programmatic solutions to natural language processing (NLP) problems. In addition to introducing the readers to programming basics, programming tools, and complete programs, we also hope to pique their interest to actively explore the broad and fascinating field of automatic natural language processing. Part I introduces programming basics and the Python programming language. Part II takes a step by step approach in illustrating the development of a program to solve a NLP problem. Part III provides some hints to help readers initiate their own NLP programming projects. INTRODUCTION Natural language processing (NLP) attempts to automatically analyze the languages spoken by humans (i.e., natural languages). For instance, you can program a computer to automatically identify the language of a text, extract the grammatical structure of sentences (see Chapter XXX of this book), categorize texts by genre (e.g., decide whether a text is a scientific or a narrative text; see Chapter XXX for classification applications), summarize a book (see Chapter XXX), etc. This chapter is aimed at teaching specialized, yet introductory, programming skills that are required to use available NLP tools. We hope that this chapter serves as a catalyst to launch NLP projects by motivating novice programmers to learn more about programming and encouraging more advanced programmers to develop NLP programs. The chapter is aimed at readers from the interdisciplinary arena that encompasses computer science, cognitive psychology, and linguistics. It is geared for individuals who have a practical NLP problem and for curious readers who are eager to learn about practical solutions for such problems. Fortifying students with the requisite programming skills to tackle an NLP problem in a single chapter is a daunting task for two primary reasons. First, along with advanced statistics, programming is probably the most intimidating task that practitioners in disciplines like linguistics or cognitive psychology can undertake. The typical student or researcher in these fields has little formal training in mathematics, logic, and computer science, hence, their first foray into programming can be a bit challenging. Second, although computer scientists have considerable experience with programming and have mastered many computer technologies, they might not be privy to the libraries or packages that are readily and freely available for NLP projects. In other words, there is a lot to cover if we attempt to address both these audiences, and it seems like an impossible challenge to design a chapter extending from the basics of programming to the specifics of NLP. Fortunately, for the reader and us, the availability of state-of-the-art NLP technologies and the enhanced usability available through easy-to-use interfaces alleviates some of these challenges. Because of space limitations, we could not achieve the coverage depth we had hoped for. We originally had planned to include programming projects in several languages such as Python, Perl, Java and PHP, along with numerous screen captures of captivating programming demonstrations. The chapter is now more focused on examples in Python. Fortunately, the materials that could not be included in the chapter (e.g., scripts, examples, screen captures), are available for your convenience on the companion website at http://patrickjeuniaux.info/NLPchapter. It also provides a series of links to NLP resources, as well as detailed instructions about how to execute the programs that are needed for the exercises. A great advantage of having a website is that it can be updated with current content, so do not hesitate to contact us if you wish to give us feedback. This chapter has three parts. Part I offers an introduction to programming. Part II gives a concrete example of programming for a specific NLP project. Part III provides general hints about starting your own NLP programming project. Readers who do not have programming experience or who do not know Python should definitely start with Part I. Individuals who have a working knowledge of Python can skip most of Part I. Among these people, the ones who do not know about NLTK could limit their reading of Part I to the section on functions and onwards. Although Part I covers a lot of material, the topic coverage is far from exhaustive. When you are done with this chapter, we encourage you to read a more complete introduction. We particularly recommend Elkner, Downey, and Meyers (2009). The same can be said of Part II. We also recommend reading Bird, Klein and Loper (2009), who give a thorough treatment of NLP programming with Python’s Natural Language Processing Toolkit (NLTK). PART I. PROGRAMMING BASICS Computers are controlled by sets of instructions called programs. Because they are somewhat simple machines, computers can only follow the most unambiguous instructions. To achieve this ideal of precision, a program is written in a restricted language. Programming languages use a specific vocabulary (i.e. a set of words), a syntax (i.e., a set of rules defining how to use these words), and semantics (i.e., the meaning of the words and rules from a programming point of view). Learning the basic rules of a language is the first step towards writing meaningful and useful programs. But prior to learning a language, it might be good to learn about the history of computer programming. Knowing the historical motivation behind programming will help you grasp what programming is all about. Programming in Context Today we usually think of a computer as a general purpose device. However, this was not always the case. Whether you consider Babbage's Difference Engine (Swade, 2002), which solved polynomial functions, or Colossus, which helped decipher the Enigma codes during World War II (Hodges, 2000) to be computers, the fact remains that a "computer" is simply something that performs calculations. In fact, before the 20th century people whose jobs were to perform complex calculations for various purposes were called 'computers' (Anderson, 2009). As the science and technology of computing advanced, man-made computers became more complex and were able to perform more complex calculations. However, the process for doing so was extremely tedious and error prone. Computers were massive beasts of machines in those days, often taking up entire rooms. Programming sometimes meant re-patching cables on a switchboard (Petzold, 2000), a far cry from the text editors and visual interfaces that we are familiar with today. At this time it became clear to the scientists involved with creating and using these machines that the difficulty of using computers was an obstruction to their widespread use and acceptance. Their solution to this problem was to create layers of abstraction between the user and the computer. This process of increasing abstraction has continued to the present day and shows no signs of stopping in the foreseeable future. For example, consider your computer's desktop. "Desktop" is just an abstraction and analogy for a physical desktop for pens and paper. Similarly, the folders on your desktop are analogous to physical file cabinets used to store paper documents. Programming languages are just another kind of abstraction over the underlying computer instructions ("machine code"). The machine code is simply a very detailed and hard to use programming language. For most applications, programmers do not use machine code but use instead modern programming languages which are designed to simplify the programmer's life (by reducing the size of the program, reducing the likelihood of programming error, etc.). Programming languages have evolved in such a way that programming is no longer restricted to the purview of professional computer scientists. So-called high level languages allow practitioners of other fields (like psychology, and linguistics) to enjoy the power and flexibility of programming. One of the goals of this chapter is to show how this is feasible. Like in all fields, it is not possible to immediately benefit from practical applications without knowing the fundamental principles underlying them. Hence, the next section is aimed at bringing you up to speed with such principles. Fundamental Concepts of Computer Programming Fundamental programming concepts include (a) values and types, (b) syntax and semantics, (c) operations, (d) variables, constants, and assignments, (e) data structures, (f) conditionals, (g) iterations, and (h) functions. We start by presenting these concepts with step-by-step examples of programs written in the Python language – a language whose simplicity seduces the most unwilling learners. While reviewing these basic ideas we also present some programming constructs that are especially relevant for NLP; these include strings, corpora, text files, input-output (I/O), etc. Before we begin, it is important to consider the two steps involved in writing a program: pseudo-code (planning) and implementation (executing). Finally, we will describe one important aspect of efficient code implementation: incremental programming. Pseudo-code As you will see in the subsequent examples, Python has a quite intuitive syntax. In some respects, Python syntax looks like pseudo-code. Pseudo-code is a high-level description of a program that makes no reference to a particular language. For instance, Table 1 presents pseudo-code for a program that translates sentences in a document. Each line is an instruction. The first line opens an input file and the last line closes it. The lines in between translate each line in the file. Pseudo-code is important because it provides a conceptual representation of what you intend to program, before you do any real programming. Planning by using some kind of pseudo-code (whether purely textual or even graphical) is an important part of conducting a s